什么是反射机制?
反射是在运行状态
中,动态获取信息
以及动态调用对象方法
的功能称为 Java 语言的反射机制
对于任意一个类,都能够知道这个类的所有属性
和方法
;
对于任意一个对象,都能够调用它的任意一个属性
和方法
;
Using java reflection we can inspect a
class
,interface
,enum
, get theirstructure
,methods
andfields
information at runtime even though class is not accessible at compile time.
eg:String 有不可变性,以通过反射技术修改其值
类:用来抽象描述一组对象
,从对象中抽取出来公有特征
和行为
反射:用来抽象描述一组类
,所有的类也具有相同的特征:
包,类名字,继承关系,实现接口,属性,方法,构造方法,块,内部类 ,注解,权限修饰符,特征修饰符,抛出异常
反射常用的方法
反射使用的步骤
正常的调用
Apple apple = new Apple();
apple.setPrice(5);
apple.getPrice()
使用反射调用
Class clz = Class.forName("com.practise.api.Apple");
# 创建对象
Constructor appleConstructor = clz.getConstructor();
Object appleObj = appleConstructor.newInstance();
# 调用set方法
Method setPriceMethod = clz.getMethod("setPrice", int.class);
setPriceMethod.invoke(appleObj, 14);
# 调用get方法
Method getPriceMethod = clz.getMethod("getPrice");
getPriceMethod.invoke(appleObj);
常见反射机制的应用
1、JDBC 的数据库的连接
2、Spring 框架里使用xml的配置模式
Spring 通过 XML 配置模式装载 Bean 的过程:
1、程序内所有XML
或Properties
配置文件加载
入内存中
2、解析xml
或properties
的内容,得到对应实体类的字节码字符串
,及相关的属性
信息
3、使用反射
机制,根据这个字符串获得某个类的Class
实例
4、动态配置
实例的属性
Spring使用反射的好处:
1、多种方式创建对象,不仅仅new
2、 方便维护
,有改变直接改配置文件
3、有时为了适应某些需求,Java类里面不一定能直接调用
另外的方法,可以通过反射机制来实现。
反射机制的原理
Class actionClass=Class.forName(“MyClass”); 进行类加载
Object action=actionClass.newInstance(); 1. 权限检测,如果不通过直接抛出异常
2. 查找无参构造器,并将其缓存起来
3. 调用无参构造方法,生成实例并返回
Method method = actionClass.getMethod(“myMethod”,null); 获取Method对象
method.invoke(action,null); 调用invoke()方法
获取Method对象
Class对象是在加载类
时由JVM构造的
JVM为每个类
管理一个独一无二的Class对象
Class对象里维护着该类的所有Method,Field,Constructor的cache
,这份cache也可以被称作根对象
调用invoke方法的流程如下:
调用Method.invoke
之后,会直接去调MethodAccessor.invoke
。MethodAccessor
所有同名method共享的一个实例,由ReflectionFactory
创建。
以调用 MyClass.myMethod(String s) 为例,生成出的MethodAccessorImpl
字节码翻译成Java代码大致如下:
public class GeneratedMethodAccessor1 extends MethodAccessorImpl {
public Object invoke(Object obj, Object[] args) throws Exception {
try {
MyClass target = (MyClass) obj;
String arg0 = (String) args[0];
target.myMethod(arg0);
} catch (Throwable t) {
throw new InvocationTargetException(t);
}
}
}
创建机制采用了一种名为inflation
的方式(JDK1.4之后)
如果该方法的累计调用次数
<=15
,会创建出NativeMethodAccessorImpl
,它的实现就是直接调用native
方法实现反射;
如果该方法的累计调用次数>15
,会由java代码创建出字节码组装
而成的MethodAccessorImpl
。
是否采用inflation和15这个数字都可以在jvm参数中调整
参考:深入理解java反射原理
反射机制的优缺点
优点:灵活性
缺点:解析字节码,解析内存中对象,性能较低
其解决方案是:
1、通过setAccessible(true)
关闭JDK的安全检查
来提升反射速度
2、多次创建一个类的实例时,有缓存
会快很多
3、ReflflectASM
工具类,通过字节码生成
的方式加快反射速度