第十周-类型信息(三)-反射

如果不知道某个对象的确切类型,运行时类型变量可以告诉你,但是有一个限制:该类在编译时必须已知。
但如果你需要获取一个不在自己程序空间的对象的引用,或者来源于网络的一串字节,被告知它是一个类,那么怎样才能获取到这个类呢?
人们想要再运行时获取类的信息的动机是希望在跨网络的远程平台上创建和运行对象的能力。这被称为远程方法调用(RMI)。
运行时获取类信息的另一个动机是基于构建的编程,学习javabean时需要对此遍进行回顾

一.反射

通过反射机制与一个未知类型打交道时,必须先加载这个类,因此这个类必须是可以获取的:可以位于本地或远程服务器上。
反射与运行时类型信息(RTTI)的区别:
RTTI:编译器在编译和运行时打开和检查.class文件,即通过普通的方式也可以调用对象的所有方法。
反射:.class文件在编译时不可获取的,所以是在运行时打开和检查.class文件的。

二.利用反射分析类

1.java.lang.reflect包提供三个类Field、Method、Constructor分别描述类的域、方法和构造器。
2.Class提供getFields、getMethods、getConstructors方法分别返回类的public域、方法和构造器数组,包括超类的共有成员;提供getDeclaredField、getDeclareMethod、getDeclaredConstructor方法返回类中的全部域、方法和构造器,包括private和protected成员,但不包括超类成员。

三.利用反射分析对象

1.通过上一节分析类可以获得类的域名称和类型--通过Class对象调用getDeclareFields方法。
2.实际上还可以通过反射的方法获取到类对象的域当前值:

Employee harry = new Employee("Harry", 3500 , 10, 1 ,1989);
Class c1 = harry.getClass();
Field f1 = c1.getDeclaredField("name");
Object v = f1.get(harry);

上述通过Field提供的get方法就可以获取域的当前值,但当“name”域为私有域时,由于反射机制受限于java的访问控制,会抛出IllegalAccessException的异常。
3.为了避免抛出异常,可以调用Field、Method、Constructor对象的setAccessible方法

f1.setAccessible();

4.get方法还有一个需要解决的问题,如果域的类型是8个基本数据类型时,基本数据类型时无法转化成Object的,这种按情况下可以调用getDouble()等方法(各基本类型都有对应的get方法)来获取域的当前值。或直接使用get方法,反射机制会自动完成装箱,将double域转化为Double对象。

四.调用任意方法

1.Method类中提供一个invoke()方法,它允许调用包装在当前Method对象中的方法。

Object invoke(Object obj1,Object... args)

例如:

Method m1 = c1.getDeclaredMethod("getName");
String name = (String)m1.invoke(harry);

与获取域当前值类似,如果方法返回值为基本数据类型,invoke方法会返回其包装器类型。

你可能感兴趣的:(第十周-类型信息(三)-反射)