Java反射API的用法
获取Class对象
- Class.forName获取Class对象
- getClass()方法
- 直接使用类名+”.class”. 对于基本数据类型, 它们的包装类型拥有一个名为”TYPE”的final静态字段, 指向该基本数据类型对应的Class对象
integer.TYPE 指向 int.class
对于数组类型 可以使用类名+ “[].class”来访问, 如int[].class
拿到Class对象后
- 使用newInstance()生成一个实例(需要一个无参构造器)
- 使用isInstance(Object)来判断一个对象是否是该类的实例, 语法上等同于instance of 关键字(JIT 优化时会有差别?)
- 使用Array.newInstance(Class,int)来构造该类型的数组
- 使用getFIelds()/getConstructors()/getMethods() 来访问该类型的成员. 带Declared的方法不会返回父类成员,但是会返回私有成员
拿到类成员后
- 使用Constructor/Field/Method.setAccessible(true)来绕开Java语言的访问限制(如private).
- 使用Constructor.newInstance(Object[])来生成该类的实例
- 使用Field.get/set(Objcet)访问字段
- 使用Method.invoke(Object, Object[])来调用方法
反射调用栈
默认情况下反射调用为委派实现, 委派给本地实现来进行方法实现来进行方法调用. 在达到阈值超过15次(第15次)委派实现会将委派对象DelegatingMethodAccessorImpl切换至动态实现(自动生成字节码(耗时)), 它将直接使用invoke指令来调用目标方法
反射性能开销原因
- 不定长参数导致的Object数组
- 基本数据类型的自己装箱拆箱
- 方法内联 (将本方法内调用的方法与自己一起编译)
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Comment