黑马程序员_反射

来源:互联网 发布:mac. 压缩软件 编辑:程序博客网 时间:2024/04/29 02:18

------- android培训、java培训、期待与您交流! ----------

 

 

反射reflect
  开发步骤
    获得所要操作的类的文件字节码文件对象
      方法一:利用Class类的forName()方法获取
        例:Class clazz =Class.forName("com.luolei.Person");
          该方法返回的是一个类的字节码文件对象
          注意传入的是类的完整路劲;包括包名
          开发一般用这种方法;扩展性最好,
      方法二:通过类的静态.class属性来获取
        例:Class clazz=Person.class;
          这种方法通过Object的.class也可以获取到文件的字节码对象;
          但是这种方式前提是你要知道别人所实现你接口的类名
          所以这种方式看是代码简单,但却没有扩展性或扩展性极差
      方法三:通过类的getClass()方法来获取
        例:Class clazz=new Person.getClass();
          这种方式需要一个类的对象,
          试想一下,你连别人创建什么类名你都不知道,你如何获取对象
          所以扩展性也极差
          说下这个方法的原理
            我们都知道万物皆对象,一个类也不例外,它也是对象
            它就是类这个类的对象
            而我们所写的程序都是以文件字节码的形式存在的,所以object有了一个静态的。class属性和一个getClass()
            所以二三方法就是利用object而创建了该类的文件字节码对象
    有了这这文件的字节码文件,那么我们要创建该类的对象
      对于无参的构造函数用newInstance()返回该类的一个对象
        例:Person person = (Preson)class.newInstance();
          该方法返回的是一个无参的构造函数的对象
      对于有参的构造函数用该类字节码文件的getConstructor()返回一个构造器对象(构造函数的类)然后用构造器的newInstance(参数)创建对象
        例:Person person = clazz.getConstructor(String.class,int.class).newInstance("罗磊",20);
          为何是String.class呢?
          原因是:不管什么类型都可以用其对应的字节码文件所描述
    现在我们要访问该类的成员变量
      一,有了字节码文件对象啦,可以直接掉用clazz.getField("age")返回一个Field(变量)对象
        但这种方法只实用于该变量是public权限的
      二,用clazz.getDeclaredField(“age”)返回一个变量(Field)对象
        这个方法能访问到所有权限的变量
        然而要是想要操纵该变量,则需要用到该类对象clazz.getDeclaredField("age").get(clazz.newInstance())
        但我们要操纵的变量是private时 可以用field.setAccessible();(强爆这个类,就是强行操作)
    访问与操作方法
      一般方法的访问与调用
        调用clazz.getMethod(“操作的方法名”,String.class,int.class(传入参数的类型))返回一个方法类对象Method
        该对象调用的invoke(“上面创建的类对象”,“小强”,56)就可以掉用操作的类的上面指定的方法
      对于私有的方法
        操作和一般方法一样 只是将getMethod改成getDeclaredField  然后用的时候要先用setAccess强暴一下
      静态方法
        操作与一般方法一致,只是调用方法时不用传入对象
      main方法
        invoke(“要操作的类的对象”,(Object)Stirng【】{“abd”,“撒旦法”})
        因为1.4版本时没有引入可变参数的概念,所以如果需要多个参数时就会用数组进行装载,而jdk在调用时会将这些数组中的元素拆分,
        所以会将上面的String[]拆分成两个String 参数传入main方法,而程序并没有操作两个string参数的main方法所以会报错,
        解决办法:将String强转成Object 让jdk误认为是传入一个对象,也就恰好达到我们想要传如多元素的数组的效果
        还有一种解决:new Object【】{String【】{“abd”,“斯蒂芬”}}封装给虚拟机拆,也能拆到我们想要的结果
  用途
    框架的开发用到
      如:我们可以定义一个接口
      让接口具有某些方法或属性
      然后在我们的框架里调用这些方法或属性
      然而你却不知道别人会为你这个接口写一个什么样的名字的类
      所以可以在框架中定义好反射机制
        通过反射机制和配置文件相关联
        只要在配置文件中告诉框架所调用的类名,方法,属性即可
        反射机制会获取配置文件中的类名,方法名。。。。
      不管别人写什么类,只要实现了接口的方法就可以在框架的程序中运行
      例:就像Eclipse  自己没有图形化界面的操作,然而只要我们导入相应的包,Eclipse就能有相关的功能
  内省(反射的特例)
    开发步骤
      调用getBeanInfo(Class<?> beanClass, Class<?> stopClass) 方法返回一个BeanInfo接口对象来省给进去的bean类,他会把bean的所有属性封装到beaninfo对象中,拿到这个beaninfo对象相当于拿到bean的所有属性
        例:BeanInfo beaninfo = Introspector .getBeanInfo( Person, Object);
      拿到这个beanifo对象后接着调用该对象的getPropertyDescriptors()就可以拿到每一个属性的属性描述器,该方法返回一个属性描述器数组PropertyDescriptor[]
         PropertyDescriptor[] pds = beaninfo.getPropertyDescriptors()
        for( PropertyDescriptor pd : pds){    可以得到每一个属性对象 }
      拿到属性描述器后再调用该描述器的getReadMethod()就可以得到这个bean的get值
        PropertyDescriptor pd = new PropertyDescriptor(“name”,Person.class);
        Method  method = pd.getWriteMethod()
        method.invoke("P(创建要操作的对象)",“罗磊”);
    用于给Bean对象反射
    开发现在多用BeanUtils
      开发步骤
        一,导包
          导入beanutils  的jar包
          而beanutils工作过程需要个日志记录器的支持,所以还需导入log4j中的Commons-logging。jar
        然后直接调用BeanUtils.setproperty(“需要操作的bean的对象”,“需要操作的属性名”,“传入的值”);
        由于beanutils 会自动将类型转为bean所需的类型,但这只能支持8种基本数据类型
          如果不是8种基本数据类型可一参阅java基础加强的18集

 

 

 

 

 

 

 

 

 

 

 

 

 ------- android培训、java培训、期待与您交流! ----------

原创粉丝点击