java高新技术之反射

来源:互联网 发布:android 源码在线查看 编辑:程序博客网 时间:2024/05/16 23:50

学习思路:

 认识Class类——>了解反射的主要组成部分——>了解类中的各个方法

 一 1 Class 类是什么?
      可以用来表示并获取java类的某一属性的类
  
 2 class获取文件字节码的方式以及适用场合
   定义java类获取class类字节码文件的方式有3种:
   class cls1 = 类名.class;
   class cls2 = 实例对象名.getClass();
   class cls3 = Class.forName("");

 3 预定义class数据类型字节码文件;
  8个基本数据类型.clas加上void.class
  判断类型是否为原始类型,判断类型是否为数组;
 
 4 什么是反射?反射就是把java中的各个部分映射成相应的java类;
 
 5 在java中各个不同组成对应的java类中方法:
  常用来获取java类中方法,变量,构造函数,修饰符,包的类有:
  Method,Constructor,Package,.Field

 A Constructor:
  a (1)得到所有的构造方法:
     Constructor[] 变量名 = 字节码.getConstructors();
   (2)得到一个构造方法
   Constructor 变量名 = 字节码.getConstructor(/*有参数时这里写参数的“数据类型.class”,没有就不用写);
 比较普通与反射创建对象的不同
  b 如何使用构造方法
   构造方法的实例变量.newInstance()//有的话,到()里面写参数(对象)
   注意,因为Construct,所以要强制类型,再赋值给变量
   如:
   Constructor constructor1 = String.class.getConstructor(StringBuffer.class);
   String str1 = (String)constructor1.newInstance(new StringBuffer("agbc"));
  c 如果通过Class.newInstance()会更加快!
 
 B Field:(与Constructor类似)
  a 得到多个成员变量
   Field[] fileds = 字节码.getFields();
  b 取其中一个
   Field field = 字节码.getField("x");//括号中是要获得的变量
   打印的时候注意要用get方法获取:
   System.out.println(field.get(field));
  上面说的都是针对public类型的,那如何对private类型的操作呢?
  c 取私有的成员变量
   Field fieldx = 字节码文件.getDeclaredField("x")//变量在()里面
   fieldx.setAccessible(true);//强制使可以获取
   System.out.println(field.get(fieldx));
 练习:
 将任意一个对象中的所有String类型的成员变量所对应的字符串内容中的"b"改为"a";
 
 思路:
  步骤一:定义一个包含多个字符串成员变量;
  步骤二:在使用这个类的方法中获取该类的Filed实例对象即字节码文件。
   因为有多个,可以使用getFields()方法获取所有的成员变量(有私有的话,就调用getDeclaredFields)。
  步骤三:获取了成员变量之后,遍历,判断是否含有成员变量为String.class的field对象;
  步骤四:如果存在,就获得该String类型对象,并保存到一个变量中;
  步骤五:使用replace方法,将所有的“b”换为“a”,并返回给一个新的String类型变量
  步骤六:使用set()方法,替换变量的值。
  步骤七:输出查看改变后的变量的值。

 问题,getFields()是否可以获得所有的成员变量,不管是public还是private

 C Method
  a 获取某一个方法:
   Method method = 字节码.getMethod(String name,参数列表类型(如int.class))
   使用方法:method.invoke(str1,1)(注:str1为字符串对象,把str1改为null后,就为静态方法了)
  JDk 1.4与JDK1.5的区别:
   JDK1.4 public Object invoke(Object obj,Object[] args)
   JDK 1.5 public Object invoke(Object obj,Object...args)
 练习:
 写一个程序,这个程序能够根据用户提供的类名,去执行类中的main方法。
 思路:
 关键弄清楚main函数如何进行参数传递,传递的是什么这个问题。

 D 数组的反射
 (1)数组基础
  a 数组的字节码文件,他们的父类都是Object(具有相同类型和维数的数组字节码文件相同);
  b 通过字节码文件实例对象调用getSuperclass方法可以得到父类的Object类对应的Class
  c 如何通过数组直接输出数组内容(Arrays.asList(实例对象名)):
  d 基本类型的一维数组可以被当做Object类型使用,不能当做Object[]使用,非基本数据类型的
  一维数组既可以当Object类型使用,又可以当做Object[]类型使用。
 (2)
  数组反射
  a 判断是否为数组类型的字节码文件:isArray();
  b 如何获取该字节码文件数组的类型
 
 HashSet类中,不要改变参与哈希地址计算的的量(更改后,就删不掉,内存泄露)
  
二 java反射及框架原理
java框架原理不是很清楚。原因:对于框架中一些方法等不清楚

 IntroSpector(检查视察,内省)——>javaBean操作-->特殊java类
 JavaBean特征:
  1,命名;符合某一种特殊命名规则的java类;public int getAge()
  get,set后面的单词,根据第二个字母决定属性名称是大写还是小写
  如:getCPU()--》CPU
   getTime()--》time

  2 通过反射的方式使用javaBean中的get和set方法以及重构方法
  
  PropertyDescriptor pd = new PropertyDescriptor(propertyName,需要提取get或set方法的字节码文件);
  (1)Method methodGetX = pd.getReadMethod();//获取对应属性读的方法
   Object retVal = methodGetX.invoke(pt1);//方法与对象相关联
  
  set方法类似
  (2)Method methodX = pd.getWriteMethod();
   methodGetX.invoke(pt1,value);//value为进行设置的属性的值
  
  重构方法:
  选中要重构的代码,右键,选中Refactor——》Extract Method-->按提示操作;
  
    3 通过遍历所有的BeanInfo方式,查找某一个属性方法
   首先,获取指定Bean对象信息的封装类:BeanInfo beanInfo = new BeanInfo(pt1.getClass());
   接着, 获取指定对象的所有封装属性 PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
   遍历属性,获取指定属性的读取值:
   

 for(PropertyDescriptor pd:pds)     {      if(pd.getName().equals(propertyName))      {       Method methodGetX = pd.getReadMethod();       retVal = methodGetX.invoke(pt1);       break;       }     }  PropertyDescriptor pd = new PropertyDescriptor(propertyName,pt1.getClas());  Method methodGetX = pd.getReadMethod();  Object retVal = methodGetX.invoke(pt1);


  总结,获取属性用下面这种,也就是2方式那种。