Java 反射机制 (二)

2014-11-24 10:51:00 · 作者: · 浏览: 1
//动态修改Customer对象的age
Object[] args1 = { new Integer(25) };
sAge.invoke(o, args1);
//动态取得Customer对象的age
Integer AGE = (Integer) gAge.invoke(o, null);
System.out.println("the Customer age is: " + AGE.intValue());
//动态修改Customer对象的name
Object[] args2 = { new String("李四") };
sName.invoke(o, args2);

} catch (Throwable e) {
System.err.println(e);
}
}


3.反射机制的功能?

① 在运行时查询并调用任意一个类所具有的成员变量和方法;

② 在运行时判断任意一个对象所属的类。例如:

String str = new String("abc");

Class c = str.getClass();

Boolean flag = c.isInstance(new String())

③ 在运行时创建类的实例;

·运行时创建实例对象

有两种办法生成实例对象:

针对无参数的构造方法,可以使用Class类里的newInstance()方法,该newInstance()方法不带参。例如:

Class c = String.class;

Object obj = c.newInstance();

要调用有参数的构造方法,就需要通过Constructor类的newInstance(Object ... obj)方法带参。例如:

//获得String的Class实例

Class clazz=String.class;

//创建一个数组,这个数组用来放要实例化对象的构造器里的参数类型

Class[] param=new Class[1];

//放入构造器中的参数类型,如果有多个,按顺序放入

param[0]=String.class;

//实例化一个构造器对象,并把放着构造器参数类型的数组作为参数传进去

Constructor constructor=clazz.getConstructor(param);

//创建一个Object数组,用于放构造器中对应的值

Object[] obj=new Object[1];

//将值放入到数组中,这里要注意,param数组中放入的是什么类型,这里就要按顺序放入

obj[0]="zhang3";

//实例化对象,并把放着构造器要传入的参数的数组传到方法中

String str=(String)constructor.newInstance(obj)

这样,我们就通过java.lang.reflect.Constructor实例化出来了String类型的对象。

·newInstance()和new关键字创建实例的比较

在初始化一个类,生成一个实例的时候,newInstance()方法和new关键字除了一个 是方法,一个是关键字外,最主要的区别在于创建对象的方式不一样,前者是使用类加载机制,后者是创建一个新类。那么为什么会有两种创建对象方式?这主要考虑到软件的可伸缩、可扩展和可重用等软件设计思想。

从JVM的角度看,我们使用关键字new创建一个类的时候,这个类可以没有被加载。但是使用newInstance()方法的时候,就必须保证:

1、这个类已经加载;

2、这个类已经链接了(即为静态域分配存储空间,并且如果必须的话将解析这个类创建的对其他类的所有引用)。而完成上面两个步骤的正是Class的静态方法forName()所完成的,这个静态方法调用了启动类加载器,即加载javaAPI的那个加载器。

可以看出,newInstance()实际上是把new这个方式分解为两步,即首先调用Class加载方法加载某个类,然后实例化。+这样分步的好处是显而易见的。我们可以在调用class的静态加载方法forName时获得更好的灵活性,提供给了一种降耦的手段。

最后用最简单的描述来区分new关键字和newInstance()方法的区别:  newInstance:弱类型。低效率。只能调用无参构造方法。

New:强类型。相对高效。能调用任何public构造。

jvm会执行静态代码段,只要记住一个概念,静态代码是和class绑定的,class装载成功就表示执行了你的静态代码了。而且以后不会再走这段静态代码了。

④ 当要调用的一个类的方法为private时,可以采用反射技术调用;

先根据完整类名加载该类——>利用newInstance或Constructor实例化——>通过getDeclaredMethods()得到私有的方法——>取消Java语言访问检查以访问private方法(即调用setAccessible(true)) ——>最后通过Method的invoke方法调用该私有方法。

⑤ 利用反射实现类的动态加载(实现java动态绑定的前提)

多态是Java面向对象语言的一个重要特性,而向上转型是实现多态的重要一步,对于面向接口或父类的引用,JVM是靠后期绑定(动态绑定)的机制进行对象类型的判定的,即在运行时才能确定调用哪些代码。而实现动态绑定的基础便是反射机制的应用,通过反射在运行时根据类名得到该类的具体信息。


三、我们学习过的知识中哪些用了反射机制?

工厂模式、Spring中IOC(或DI)、AOP都使用到了java反射机制