Java学习日记----反射

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

 

1 Class类
   1.1 反射不是Java1.5的新特性,而是从1.2就有的特性,在以后学习到框架都要用到反射,要了解反射,就要先了解Class类.
   1.2 Class代表一类事物,Java用类描述一类事物的共性这类事物有什么属性,至于属性的值,则由该类事物具体实例(对象)来确定,例如,在Java中的各个类,这也是一类事物,也可以用一个类来表示,这个类就是Class类.
   1.3 一个Java类可以用一个Class对象来表示,一个类中的成份:成员变量,成员方法,构造方法,包等等信息,也可以用一个个Java类来描述.比如,一辆汽车是一个类,汽车中的发动机,变速箱也可以是一个个Java类,描述Java类的Class类显然要提供一系列的方法,来获取其中的变量,方法,构造方法,修饰符,包等信息,这些信息就是用相应的类的实例来表示,这些相应的类分别是:Field,Method,Constructor,Package等等.
   1.4 字节码
      当在程序中要使用到某一个类时,首先要从硬盘上将这个类的class文件的二进制代码加   载到中,而后用这份二进制代码创建一个个这个类的对象.
   1.5 获得字节码对应的实例对象(Class对象)的方法
      a> 类名.class
      b> 对象的getClass()方法.
      c> Class类有静态方法forName(String name).
      d>得到某个类的字节码有两种情况:
         1> 这个类的字节码已经加载到内存中,直接找到返回就可以了.
         2> 这份字节码不在内存中,于是用类加载器去加载,加载进来之后,缓存起来,同    时返回这份字节码
   1.6 做反射一般是用Class类有静态方法forName(String name),因为在写源程序时,还不知道类的   名字,在运行时,传入一个字符串,里面包含有类的名字.
      有九个预定义的Class对象---->八种基本数据类型和void,在基本数据类型的包装类中,   有一字段TYPE,就代表这个所包装的基本类型的实例(Class对象).
2 Constructor类
   2.1 Constructor类用于描述类中的构造方法.
   2.2 Constructor类中的getConstructor()方法,用于获取某个类的氖构造方法,如Class.forName("Java,lang.String").getgetConstructor()就是获取String类中的所有构造方法.为了得到类中的某一构造方法,可以通过对应的构造方法的参数的类型的字节码,如Class.forName("Java,lang.String").getgetConstructor(StringBuffer.class)就是获   取了String类中的String(StringBuffer sb)构造方法
   2.3 Constructor类中的newInstance()方法,可以创建对象,需要注意的是,编译器只知道Constructor实例是代表某一个类的构造方法,而不知道是哪个类的构造方法,所以newInstance()方法返回的是Object对象.
   2.4 在Class类中也有newInstance()方法,但只适用于空参数的构造方法,对于有参数的构造方法,只能获取Constructor实例,再创建对象.
3 Field类
   3.1 Field fieldy = dt.getClass().getField("y");
      fieldy不是对象的变量y,而是类中的变量y,用fieldy去获取某个对象中的y的值:当y被公有时(public修饰),fieldy.getField(Object obj);当y被私有时,先setAccessible(true),再fieldy.getField(Object obj),称为"暴力反射"
      总:从个体中抽取共性部分,对所有实例都有用.
4 Method类
   4.1 Method类是用于描述类中的方法的.
   4.2 Method对象是通过Class类的getMethod()方法获取的,但是getMethod()是获取类中所有的方法对象,当要获取某一个方法对象时,可以用getMethod(String methodName,Class<?>...parameterType)获取.
   4.3 通Method类中的invoke(Object obj,Object...args)方法,可以调用Method实例对象对应的方法,如果第一个参数为空,说明该对象所属的方法是一个静态方法.
   4.3 对接收数组参数的成员方法进行反射
      启动Java程序的main方法的参数是一个数组,String[] args,通过反射来调用这个方法时,如何为invoke()方法传递参数呢?按Java1.5的语法,整个数组是一个参数,按Java1.4的语法,数组中的每一个元素对应一个参数,把String[]传给invoke()时,会按哪种方式处理呢?1.5肯定要兼容1.4的语法,会按1.4的语法进行处理,把数组打散成若干个单独的参数,所以在给invoke()方法传入参数时要注意,特别是接收数组参数的方法时.
      解决方案:

        a> invoke(obj,new Object[]{new String[]{}});
          b> invoke(obj,(Object)new String[]{});
          a>方法是给数组包上一层皮,由编译器去拆,b>方法是告诉编译器,没有皮了,可以不用拆.
 
5 数组的反射
   5.1  int[] a1 = new int[3];
      int[] a2 = new int[4];
      int[][] a3 = new int[3][2];
      String [] a4 = new String[3];
  
      a1.getClass() == a2.getClass()  //---true
      a1.getClass() == a3.getClass()  //---false
      a1.getClass() == a4.getClass()  //---false
  
      a1.getClass().getSuperclass().getName();  //----java.lang.Object
      a4.getClass().getSuperclass().getName();  //----java.lang.Object
    
      Object[] ibj1 = a1;  //---编译通过不了
      Object[] ibj3 = a3;  //---可以通过编译
      Object[] ibj4 = a4;  //---可以通过编译
  
      从上可以看出,数组类型的父类是Object类,基本类型的一维数组仅能当作Object类用,而  基本类型的二维数组和引用类型的数组,不仅可以当作Object类用,还可以当作Object[]用
   5.2 int[] a = new int[3];
      在反射中不能知道a是什么类型的数组的,因为a的反射后的类型是Class类型,可以通过  isArray()方法,判断a是否是数组,再通过Array中的方法可以操作a.

posted @ 2012-12-08 00:08  叶征东  阅读(131)  评论(0编辑  收藏  举报