zoukankan      html  css  js  c++  java
  • 2016/05/04(反射)

    反射:重点----每天都用反射,但是每天都不写反射    
    Java的反射技术是java程序的特征之一,它允许运行中的Java程序对自身进行检查,或者说“自审”,并能直接操作程序的内部属性。

    使用反射可以获得Java类中各个成员的名称并显示出来。简单的说,反射就是让你可以通过名称来得到对象(类,属性,方法)的技术。

    反射的作用
     可以通过反射机制发现对象的类型,发现类型的方法/属性/构造器
     可以创建对象并访问任意对象方法和属性等

    主要点:运行时探究和使用编译时未知的类

    Dog d1 = new Dog();这样一个类在创造的时候经历了哪些过程呢?
    简单的来说
    类加载:由类加载器完成,类的class文件读入内存后,就会创建一个java.lang.Class对象。一旦某个类被载入JVM中,同一个类就不会再次被载入。
    连接:把类的二进制数据合并到JRE中。

    初始化 :JVM负责对类进行初始化,也就是对静态属性进行初始化。在Java类中,对静态属性指定初始值的方式有两种:
    (1)声明静态属性时指定初始值;
    (2)使用静态初始化块为静态属性指定初始值。

    在我们上边的案例中:
    1.JVM利用DogClassLoader先将Dog类加载到内存,然后马上产生了一个Class类型的对象,该对象可以看成是一个模型,以后无论创建多少个Dog类的实例都是利用该模型来生成。
    ---所以一个类所对应的Class类型的对象只有一个。

    根据这个模型生成Dog类实例反射正是利用了java的这种加载方式主动完成了对象的创建及使用。

    使用反射:
    遵循三个步骤
    第一步是获得你想操作的类的 java.lang.Class 对象
    第二步是调用诸如 getDeclaredMethods 的方法
    第三步使用 reflection API 来操作这些信息


    简单案例01:
      Class c1 = String.class;
      Class c2 = Class.forName("java.lang.String");
      Class c3 = "abc".getClass();


    实验2:通过反射做一些事情
      Integer a=13;
      Class c=a.getClass();//获得了a的类型


    案例03:
      Integer a=13;
      Class c=a.getClass();
      Field[] field=c.getDeclaredFields();
      for(Field f:field){
       System.out.print(f.getType()+" ");
       System.out.println(f.getName());
      }
    我们获得了Integer类中的所有属性
    那能不能修改呢?
      Dog d=new Dog();
      Class clazz=d.getClass();
      Field field=clazz.getDeclaredField("num");
      field.set(d, 1000);
      System.out.println(field.get(d));


    案例04:
      Class c1=Outer.class;
      Method[] methods=c1.getDeclaredMethods();
      for(Method method:methods){
       System.out.print(method.getName()+" ");
       System.out.print(method.getReturnType()+" ");
       System.out.println(method.getParameterTypes());//这里如果是数组的话该怎么处理
      }
    获得该类中所有的方法
      Dog d=new Dog();
      Class clazz=d.getClass();
      Method method=clazz.getDeclaredMethod("show",int.class,String.class);
      method.invoke(d,10,"zhangsan");

    案例05:
     Integer a=13;
      Class c=a.getClass();
      Class c1=Outer.class;
      Constructor [] constructors=c.getDeclaredConstructors();
      for(Constructor constructor:constructors){
       System.out.print(constructor.getName()+" ");
       System.out.println(Arrays.toString(constructor.getParameterTypes()));
      }
    获得所有的构造函数
     

    重点:通过反射来创造类的实例

    实验01:
    通过类名来创建类实例
      Class cls=Outer.class;//obj指向的A类的对象 总体来说还是Object
      Object o=cls.newInstance();
    ------------------------------------------------------注意它和我们的实例对象一样吗
     Class<?> clazz=Class.forName("包名.类名");
     Wode o=(Wode) clazz.newInstance();

    注意点:
    Class.forName() 静态方法,可以利用类名在 CLASSPATH 中查找对应的类,并且装载到内
    存, 返回这个” class“
    Class.forName()加载类的过程采用” 懒惰方式,即检查发现如果已经加载了(内存中存在)就丌再加载,直接返回已经加载的类,相当于“手工”去检查内存中是否已经加载了某个类

    .newInstance()方法,会利用默认(无参数)构造器创建类实例(实例对象)


    补充点:获得class对象三种方式
    方式一:如果一个类的实例已经得到,你可以使用
            【Class c = 对象名.getClass(); 】
           例:  TextField t = new TextField();
                   Class c = t.getClass(); 
                   Class s = c.getSuperclass();

    方式二:如果你在编译期知道类的名字,你可以使用如下的方法                 
      【 Class c = JButton.class;  】
      或者         Class c = Integer.TYPE;

    如果类名在编译期不知道, 但是在运行期可以获得, 你可以使用下面的方法
                【 Class c = Class.forName(strg); 】


    在这里要注意:
    newInstance: 弱类型。低效率。只能调用无参构造。
    new: 强类型。相对高效。能调用任何public构造。
    newInstance()是实现IOC、反射、面对接口编程 和 依赖倒置 等技术方法的必然选择,new 只能实现具体类的实例化,不适合于接口编程。


    通过反射操作对象属性

      Class clss=Outer.class;
      Object o=clss.newInstance();
      Field field=clss.getDeclaredField("num");
      Object val=field.get(o);
      System.out.println(val);

    上边的实验,我们发现用这种方式也是可以的Class cls=Outer.class;
    --------------------------
    接着上边的实验,我们发现了
      Object val=field.get(o);
      val=15;
      Object val2=field.get(o);
      System.out.println(val);
    通过这种方式完全可以修改我们的属性

  • 相关阅读:
    LeetCode.152
    python
    python
    python
    python
    python
    python
    python
    PyCharm2020.1激活码破解教程
    Python GUI编程(Tkinter)17、Menu鼠标右键菜单
  • 原文地址:https://www.cnblogs.com/chenyangpeng/p/5459925.html
Copyright © 2011-2022 走看看