反射小结

反射小结

 

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

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

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

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

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

 

 

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

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

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

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

Class<String> cl1 = String.class;

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

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

Class<? extends String> 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<T> getConstructor(Class<?>... parameterTypes)

获得特定的public构造方法.

public Constructor<?>[] getConstructors()

获得public构造方法。

 

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

 

public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)

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

public Constructor<?>[] getDeclaredConstructors()

获得所有级别的构造方法

 

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

public Constructor<T> getConstructor(Class[] parameterTypes)

public Constructor<T> 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<String> 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<len;i++){

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

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

                     

             }

      }else{

             System.out.println(obj);

      }

      

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值