Java反射机制浅析

来源:互联网 发布:口袋妖怪能力数据 编辑:程序博客网 时间:2024/06/12 15:43

1、相关知识

Java允许通过程序化的方式间接对Class进行操作。Class文件经由类装载器装载后,在JVM中形成一份描述Class结构的元信息对象。通过该元信息可以知道Class的结构信息:比如累得成员、构造函数、属性和方法等。用户可以通过该元信息去间接调用Class对象的功能。

(1)类装载器ClassLoader

类装载器可以寻找类的节码文件,并构造出类在JVM中的表示对象。经过三个步骤:装载(查找和导入Class文件)->链接(执行校验、准备和解析步骤)->初始化(对类的静态变量、静态代码执行初始化工作)。这些都有ClassLoader及其子类完成。

(2)ClassLoader的重要方法:

a、ClassloadClass(String name)
name参数是需要装载类的全名称。还有一个重载方法是:loadClass(String name, boolead resove),resove告诉装载器是否要解析该类。在初始化类之前,应该考虑是否需要解析该类。但并非所有的类都需要解析。如果JVM只需要知道该类是否存在或找出该类的超类,那就不需要解析。
b、ClassdefineClass(String name, byte[]b, int off, int len)
将类文件的字节数组转换成JVM内部的java.lang.Class对象。字节数组可以从本地文件系统、远程网络获取。name为类的全限定名。
c、ClassLoadergetParent
获取该装载器的父装载器。

2、反射机制说明

如前面所说的:用户可以通过该元信息去间接调用Class对象的功能。这些反射类对象在java.reflect中包含。下面说比较重要的反射类:
(1)Constructor:构造函数反射类
通过Class#getConstructors()可以获得该类的所有构造函数反射对象数组。Construct有个方法:newInstance(Object... initargs),可以创建一个类对象,就像new关键字一样。
(2)Method:类方法的反射类。通过Class#getDeclearMethods()可以获取类的所有方法数组。Method还有很多获取类方法信息的方法:
a、Class getReturnType():获取方法返回值类型;
b、Class[] getParametersTypes():获取方法的传入参数类型数组;
c、getExtensionTypes():获取方法的异常类型数组;
d、Annotation[][] getParameterAnnotations():获取方法的注解信息
(3)Field:类的成员反射类。通过Class#getDeclearFields()获取成员变量反射数组。

3、举例说明

我们首先定义辅助类Car,包括属性有:牌子-brand、颜色-color和z最大时速-maxSpeed。

package lucene.mylucene.module;/** * @author fanyp * @datetime 2017年7月13日 上午11:13:17 * @desc Car */public class Car {private String brand;private String color;private Integer maxSpeed;public Car() {}public Car(String brand, String color, Integer maxSpeed) {this.brand = brand;this.color = color;this.maxSpeed = maxSpeed;}public String getBrand() {return brand;}public void setBrand(String brand) {this.brand = brand;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}public Integer getMaxSpeed() {return maxSpeed;}public void setMaxSpeed(Integer maxSpeed) {this.maxSpeed = maxSpeed;}/** * @authorfanyp * @datetime 2017年7月13日 上午11:13:31 * @param * @desc车属性输出介绍 */public void introduce() {System.out.println("方法introduce的执行结果:" + "bradn:" + brand + ";\ncolor:" + color + ";\nspeed:" + maxSpeed);}}

上面我们定义了一个简单的类Car,并填充了一些基本的属性。下面我们通过反射来给这些属性设定值,并且调用其中的方法:
package lucene.mylucene.module;import java.lang.reflect.Constructor;import java.lang.reflect.Method;/** * @author fanyp * @datetime 2017年7月13日 上午11:15:13 * @desc 反射测试类 */public class ReflectTest {public static Car initDefaultConstruct() throws Exception {ClassLoader loader = Thread.currentThread().getContextClassLoader();Class<?> clazz = loader.loadClass("lucene.mylucene.module.Car");//注意这里是Car类的完全限定名Constructor<?> constructor = clazz.getConstructor();Car car = (Car) constructor.newInstance();Method setBrand = clazz.getMethod("setBrand", String.class);setBrand.invoke(car, "BMW");Method setColor = clazz.getMethod("setColor", String.class);setColor.invoke(car, "RED");Method setMaxSpeed = clazz.getMethod("setMaxSpeed", Integer.class);setMaxSpeed.invoke(car, 400);return car;}public static void main(String[] args) throws Exception {Car car = initDefaultConstruct();car.introduce();}}

运行后可以看到:



原创粉丝点击