反射



一、反射的概念

      一个类有多个组成部分,例如:成员变量、方法、构造函数等。反射就是加载类,并解剖出类的各个组成部分。反射通常用来开发框架。


二、加载类


      使用反射的第一步就是加载类,Java中的CLass类用于代表某一个类的字节码,它提供了加载某个;类字节码的方法:forName()。forName方法用于加载某个类的字节码到内存中,并使用class对象进行封装。


       使用forName()时必须提供需要加载的类的完整名称,例如:


class.forName("cn.itcast.reflect.Person");

       其中cn.itcast.reflect为上级包名,Person为类名,使用该方法后,就将该类的字节码从硬盘中加载进内存了。


       获取字节码的另外两种方式:

Class cla=new Person().getClass(); 

 

         Class cla=Person.class;

三、使用Class对象提供的方法反射类的成员


反射构造函数:        


//加载类
      Class cla=class.forName("cn.itcast.reflect.Person");
      //使用getConstructor解剖出公有无参构造函数,并返回Constructor对象。
      Constructor cst=cla.getConstructor(null);
      //使用 Constructor的newInstance方法创建对象
      Person p=(Person)cst.newInstance(null);


      getConstructor只能得到公有的构造函数,如果想获得私有的构造函数,则需要调用 getDeclaredConstructor方法,并实现暴力反射。


//解剖出私有无参的构造函数,并返回Constructor对象
      Constructor cst=cla.getDeclaredConstructor(null);
      //实现暴力反射
      cst.setAccessible(true);



      创建对象还有另外一种方法:


//直接通过Class的newInstance方法来创建对象,但使用这种方法是默认调用了无参的构造方法,所以类中必须要有无参的构造方法
      Person p=(Person)cla.newInstance();


       反射类的方法:      


//加载类
      Class cla=class.forName("cn.itcast.reflect.Person");
      //使用getMethod解剖出.Person类中的方法,并返回Method对象。
      Method met=cla.getMethod(Object obj,Object obj);//前面为方法名,后面为参数类型
      //调用解剖出来的方法
      met.invoke(Object obj,Object… obj);//前面为方法名,后面为参数


       getMethod只能得到公有的方法,如果想获得私有的方法,则需要调用 getDeclaredMethod方法,并实现暴力反射。


//解剖出Person类中的方法,并返回Method对象。
      Method met=cla.getDeclaredMethod(Object obj,Object obj);//前面为方法名,后面为参数类型
      //实现暴力反射
      met.setAccessible(true);
      //调用解剖出来的方法
      met.invoke(Object obj,Object… obj);//前面为方法名,后面为参数


       如果该方法为静态,则使用invoke调用方法时不需要传递对象。


met.invoke(null,Object… obj);


       如果解剖的方法是主方法,使用invoke调用方法时传递的参数时,会默认将数组拆开取其中的元素,所以必须对参数进行处理。


met.invoke(null,(Object)new String[2]);


 反射类的字段:


//加载类
      Class cla=class.forName("cn.itcast.reflect.Person");
      //使用getField解剖出.Person类中的字段,并返回Field对象。
      Field fd=cla.getField(Object ob);//参数为字段名
      //使用 Field的get方法传递对象,获得字段,并返回object对象。
      fd.get(Object obj);
      //使用Field的getType方法可以返回字段的类型
      fd.getType();
      //使用 Field的set方法传递对象和值,给该字段赋值。
      fd.set(Object obj,Object obj);//前面为对象,后面为要赋的值


        getField只能得到公有的字段,如果想获得私有的字段,则需要调用 getDeclaredField方法,并实现暴力反射。



//解剖出类的私有字段,并返回Field对象。
        Field fd=cla.getDeclaredField(Object ob);//参数为字段名
        //实现暴力反射
        fd.setAccessible(true);