反射

JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制

好处:

作用:

使用反射创建对象

String s = String.class.getConstructor(String.class).newInstance("str");

关键类

stateDiagram-v2  direction LR  state "Class" as c1  c1 --> Field: getFields() getDeclaredFields()  c1 --> Package: getPackage()  c1 --> 接口(Class): getInterfaces()  c1 --> Constructor: getConstructors()  c1 --> Method: getMethods() getDeclaredMethods()  c1 --> 修饰符(int): getModifiers()  c1 --> 父类(Class): getSuperclass()  c1 --> Annotation: getAnnotations()

Class

CharSequence.class.isAssignableFrom(String.class)

类型的比较可以通过 instanceof 或者 isInstance接口来进行 这两个接口的比较是有考虑继承关系。

另外一种比较可以通过比较两个class对象,这种方式没有考虑继承关系。

安全性

反射提供的 AccessibleObject.setAccessible​(boolean flag) 可以在运行时修改成员访问限制

在后续的版本中,Java 逐渐收紧了这个功能,只有在模块描述文件中开放权限才是合法的:

module MyEntities {    // Open for reflection    opens com.mycorp to java.persistence;}

当然,目前只是报一个警告,只是不知道在哪个版本中就会彻底关闭这个功能

应用

JAVA反射增强

org.reflections

功能

NoClassDefFoundError 和 ClassNotFoundException

  1. 如果编译时能找到这个类,但运行时找不到这个类,就抛出NoClassDefFoundError
  2. 如果通过Class.forName 进行加载找不到,则会抛出 ClassNotFoundException

反射的实现

一个通过本地方法来实现反射调用,即通过 JNI 来进行方法调用,另一个则使用了委派模式,即动态代理生成对具体类的具体方法方法调用

反射的开销

  1. 变长参数方法需要创建 Object 数组
  2. 基本类型的自动装箱、拆箱
  3. 方法内联优化失效