分享

java

 ForTheDraem 2019-02-21

个人理解反射可以不通过new这个关键字产生一个指定的类,并可以调用成员变量,普通方法,构造方法等。

首先看一个代码例子

  1. import java.util.Date;
  2. /**
  3. * 反射取得实例化对象的三种方式
  4. * @author 76519
  5. *
  6. */
  7. public class TestDemo1 {
  8. public static void main(String[] args) {
  9. //方式一 需要先实例化类 再反射
  10. Date date = new Date();
  11. //此处的泛型 只能是 "?"
  12. Class<?> dts = date.getClass();
  13. //System.out.println(dts);
  14. System.out.println(dts.getName());

  15. //方式二 不需要实例化 但需要引入包----import java.util.Date;
  16. Class<?> dts2 = Date.class;
  17. System.out.println(dts2.getName());

  18. //方式三 不需要实例化操作 也无需引入包
  19. try {
  20. //根据类名称(全路径名) 反射到类
  21. Class<?> dts3 = Class.forName("java.util.Date");
  22. System.out.println(dts3.getName());
  23. } catch (ClassNotFoundException e) {
  24. e.printStackTrace();
  25. }

  26. //总结:
  27. //除了方式一会产生实例化对象之外 其他两种都不会产生实例化对象
  28. }
  29. }

从例子中可以看出,获取一个反射后的对象有三种方式:

|-实例化对象.getClass();   此方法需要先实例化对象 并导入类的路径  也就是需要先new

|-对象.class;//无需实例化对象  但必须导入类的路径

|-Class.forName("类的全路径"); 无需导入类的路径,因为此时forName中写的就是全路径(包名.类名)

 

取得一个反射后的类后,可以通过实例化操作,获得此类的操作权。

例子:取得实例化对象

  1. /**
  2. * 取得实例化对象就意味着取得了一个 指定类 的 操作权
  3. * @author 76519
  4. *
  5. */
  6. public class TestDemo {
  7. public static void main(String[] args) throws Exception {
  8. Class<?> cls = Class.forName("java.util.Date");//使用字符串描述使用的类
  9. //反射出的对象 采取 newInstance() 进行实例化
  10. Object obj = cls.newInstance();//实例化对象,等价于:new java.util.Date
  11. System.out.println(obj);

  12. //Object类型 向下 转型
  13. Date date = (Date) obj;
  14. System.out.println(date.getTime());
  15. }
  16. }
  1. Thu Aug 23 10:48:38 CST 2018
  2. 1534992518173

   上面是运行结果,newInstance()方法是java.lang.Class的方法,专用于反射类的实例化对象的创建。返回的是一个Object类型,直接打印Object类型的变量是调用了他的toString(),也就是打印的时间。下面的getTime()方法是java.util.Date的方法,Object中不存在,所以需要向下转型。

   此处的代码有个很严重的细节问题,就是"被反射"的类中必须有无参构造(或无参构造不是public修饰的!),下面看个没有无参构造时产生的问题

例子:没有无参引发的血案

  1. class Humen{
  2. private String userName;
  3. private int age;
  4. //无参构造
  5. //public Humen() {}
  6. //有参构造
  7. public Humen(String userName,int age) {
  8. this.userName = userName;
  9. this.age=age;
  10. }
  11. @Override
  12. public String toString() {
  13. return "Humen [userName=" + userName + ", age=" + age + "]";
  14. }
  15. }
  16. /**
  17. * 无参的重要性
  18. * @author 76519
  19. */
  20. public class TestDemo3 {
  21. public static void main(String[] args) throws Exception{
  22. Class<?> humenCls = Humen.class;
  23. //当没有无参构造时
  24. //java.lang.NoSuchMethodException: refelect.第二天.Humen.<init>()
  25. System.out.println(humenCls.newInstance());
  26. }
  27. }

运行下,出现如下问题:

  1. Exception in thread "main" java.lang.InstantiationException: refelect.Humen
  2. at java.lang.Class.newInstance(Unknown Source)
  3. at refelect.TestDemo3.main(TestDemo3.java:29)
  4. Caused by: java.lang.NoSuchMethodException: refelect.Humen.<init>()
  5. at java.lang.Class.getConstructor0(Unknown Source)
  6. ... 2 more

有人会说到,如果没有无参构造,就不能实例化我获取的反射的类了么,答案是  不是! 有无参构造函数只是说实例化获取到的反射的类更加简单容易,下面我们看下没有无参构造的情况下,如何获取我们反射得到的类的实例化对象。

  1. import java.lang.reflect.Constructor;

  2. class Humen{
  3. private String userName;
  4. private int age;
  5. //无参构造
  6. //public Humen() {}
  7. //有参构造
  8. public Humen(String userName,int age) {
  9. this.userName = userName;
  10. this.age=age;
  11. }
  12. @Override
  13. public String toString() {
  14. return "Humen [userName=" + userName + ", age=" + age + "]";
  15. }
  16. }
  17. /**
  18. * 无参的重要性
  19. * @author 76519
  20. */
  21. public class TestDemo3 {
  22. public static void main(String[] args) throws Exception{
  23. Class<?> humenCls = Humen.class;
  24. //当没有无参构造时
  25. //java.lang.NoSuchMethodException: refelect.第二天.Humen.<init>()
  26. //System.out.println(humenCls.newInstance());

  27. //解决思路
  28. //通过获取反射对象中的构造方法 实例化对象 --- 此处使用的方法是根据 指定类型获得指定的构造方法
  29. Constructor<?> cons = humenCls.getConstructor(String.class,int.class);
  30. //获取构造的对象 并 进行实例化
  31. System.out.println(cons.newInstance("香蕉不拿拿先生",25));
  32. }
  33. }

这个方法是获取其他的有参构造方法,通过

 java.lang.Class.getConstructor(Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException

Class对象的getConstructor(Class<?>... parameterTypes)获取指定的构造方法,其中使用到了一个"可变参数"的类型,其实传递的就是一个参数类型的数组,可以是没有,1个或多个参数。

通过获取到指定的构造方法对象后,调用

java.lang.reflect.Constructor.newInstance(Object... initargs) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException

java.lang.reflect.Constructor的newInstance()进行获取反射的实例化对象!

相对于有无参构造函数来说,此方法太麻烦,所以开发中需要写类的无参构造-----我琢磨到这时,才发现无参构造的重要性。

通过以上的方法,我们现在可以利用反射获取到类的对象了,并通过调用其中的构造方法获取实例化对象。

注意:任何该类中的   普通方法   调用,都必须通过先实例化对象,再进行调用普通方法哦。

暂时先说在这吧,后续会继续做出总结

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多