Chinaunix首页 | 论坛 | 博客
  • 博客访问: 155705
  • 博文数量: 17
  • 博客积分: 357
  • 博客等级: 一等列兵
  • 技术积分: 706
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-12 16:49
文章分类

全部博文(17)

文章存档

2013年(3)

2012年(14)

我的朋友

分类: Java

2012-09-30 10:24:57

反射小结

转载自http://blog.csdn.net/xjwangliang/article/details/6553189

反射机制提供的功能很多,比如:

1、运行时判断对象所属的类

2、运行时创建一个类的对象

3、运行时得到类多具有的方法和属性

4、运行时改变属性和执行方法

 

 

1.每一种类型的对象和类对应同一个Class对象。

1)得到对象的Class对象:对象.getClass()

2)得到类的Class对象:类.class.

以上两种还是有些区别,比如:

Class cl1 = String.class;

对象getClass()返回Class对象的类名>

Class cl2 = (Class) "String".getClass();或者

Class cl3 = "String".getClass();

另外泛型类型,编译之后去掉了泛型信息。

 

2.Java中每一种类型都有对应的Class对象,对于八种基本类型intshortbytelongfloat

doublebooleanchar,获得其对应的Class对象

xxx.class

也可以使用对应的包装类型获得(例如int的包装类型为Integer

XXX.TYPE

另外,对于void这个特殊的类型,它也有Class

void.class,相应的也可以Void.TYPE,其中Void是类。

以上的9Class类型是基本类型,也就是说isPrimitive(xxx)返回true

 

3.得到对象的Class之后,我们可以得到对象的构造方法,方法,字段,包,对应于:

 

3.1Constructor】代表构造方法。.

 

public Constructor getConstructor(Class... parameterTypes)

获得特定的public构造方法.

public Constructor[] getConstructors()

获得public构造方法。

 

【注意】:上面的两个方法都是获得public的构造方法,但是有个特例,对于类中隐含的默认构造方法(不是自定义的无参构造方法),虽然它是public,却不能使用上面的方法,必须显示定义public的构造方法,或者使用下面的方法。

 

public Constructor getDeclaredConstructor(Class... parameterTypes)

获得所有级别的特定构造方法

public Constructor[] getDeclaredConstructors()

获得所有级别的构造方法

 

【注意】:可变参数是JDK1.5的新特性,以前使用数组表示

public Constructor getConstructor(Class[] parameterTypes)

public Constructor getDeclaredConstructor(Class[] parameterTypes)

可变参数可以接收数组,但是反之不行

 

得到Constructor之后,可以通过Constructor可以获得实例对象:

public T newInstance(Object... initargs)

JDK1.5以前为public T newInstance(Object[] initargs)

【注意】:对于private的构造方法,要获得实例对象,必须先要Constructor对象.setAccessiable(true)

 

【例子】:

不使用泛型

      Constructor c = String.class.getDeclaredConstructor(StringBuffer.class);

String s = (String) c.newInstance(new StringBuffer("wangliang"));//需要转型

      System.out.println(s);

使用泛型

      Constructor c1 = String.class.getConstructor(StringBuffer.class);

      String s1 = c1.newInstance(new StringBuffer("wangliang1"));//对于泛型就不需要转型

      System.out.println(s1);

 

Class也有个public T newInstance(),它是调用Constructorpublic T newInstance()

创建此 Class对象所表示的类的一个新实例。使用默认无参构造。如果该类尚未初始化,则初始化这个类。而且此newInstance()方法不必显示定义public的构造方法,类中有隐含的默认构造方法。

 

同一个Class或者Constructor的调用两次newInstance()方法得到的是不同的对象

 

由无参构造方法获得对象:

Class对象.getConstrutor(new Class[]{}|null|).newInstance(new Object[]{}|null|)不一定要对应

3.2Field】代表属性。

与构造方法类似,Field也有类似的方法:

public Field getField(String name)

public Field[] getFields()

 

以上只针对public级别,下面的方法可以访问任意级别:

 

public Field getDeclaredField(String name)

public Field[] getDeclaredFields()

 

 

【获得属性的值】

以上方法只是获得原对象的属性对应的对象,要获得属性的值

 

Field对象.get(null)获得静态属性的值

Field对象.get(原对象)获得(也可以是静态)属性的值

 

【设置属性的值】

Field对象.set(null)设置静态属性的值

Field对象.set(原对象,Object参数)设置(也可以是静态)属性的值

 

【注意】:对于privateField,要获得和设置值,先要Field对象.setAccessiable(true)。另外对于final(非static)的Filed对象,设置值,即调用set()方法,必须Field对象.setAccessiable(true)

 

【注意】:

1、对于static final的属性(声明时就初始化了),set()方法出错,无法改变。

2、对于static属性可以改变。

3、对于final的属性调用set()方法,都先要setAccessible(true),这与属性的访问级别不是一回事(即使是public也要设置)。

4、对于一般非staticfinal属性,如果是声明时就初始化了,也无法改变属性的值(但不会报错),只有在构造方法中初始化的才可以改变。

 

3.3Method】代表方法。

与前面类似:

public Method getMethod(String name,Class... parameterTypes)

public Method[] getMethods()

 

以上只针对public级别,下面的方法可以访问任意级别

 

public Method getDeclaredMethod(String name,Class... parameterTypes)

public Method[] getDeclaredMethods()

 

【执行方法】获得了Medthod对象之后,可以执行方法:

Method对象.invoke(null, Object参数列表);null表示静态方法

Method对象.invoke(原对象,Object参数列表);执行方法

 

【注意】:对于privateMethod,要获得和设置值,先要Method对象.setAccessiable(true)。如果方法没有参数,参数列表可为空或者null或者空的Object数组(new Object[]{})。

如果参数为基本类型,则首先适当地将其包装在对象中。但是,如果该值的类型为一组基本类型,则数组元素不被包装在对象中;换句话说,将返回基本类型的数组。如果底层方法返回类型为 void,则该调用返回 null。如果参数为数组,Object参数列表就是new Object[]{new 类型[]{元素列表}}

 

获得属性和方法所代表的对象都可以直接通过class得到,而不必通过对象;但是要得到属性的值(除了静态属性)以及执行方法(除了静态方法),都要通过对象。

 

3.4Array

Array允许对数组进行动态操作

判断Class是否为数组:isArray(),从而就知道了相应的对象是否为数组。但是能否打印一般类型的数组呢?

 

参数是一般的对象,obj.lengthobj[i]obj[i].getClass()这些方法都不存在,因为objObject的对象,无这些方法和属性。也没法强制转换,因为不知道类型数组元素的类型(obj.getClass()得到的是数组的类型,而不是元素的类型;obj[i].getClass()是可以得到元素类型),就算知道,也要做多次判定。但是我们可以:

 

private static void printObject(Object obj) {

      Class clazz = obj.getClass();

      if(clazz.isArray()){

             int len = Array.getLength(obj);

             for(int i=0;i

                    System.out.println(Array.get(obj, i));

                    //对应的set():static void set(Object array, int index, Object value)

                     

             }

      }else{

             System.out.println(obj);

      }

      

}

阅读(1948) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~