什么是反射?
反射是各类框架的灵魂,允许我们在JVM运行时提供分析类,操作类的能力。
反射是一种在运行时检查和修改类、方法、属性等程序结构的能力。通过反射,可以动态地获取和操作程序的元数据,包括类的字段、方法、注解等信息。
反射的使用
获取 Class 对象的四种方式
知道具体类的情况下可以使用
Class alunbarClass = TargetObject.class;
通过 Class.forName()
传入类的全路径获取
Class alunbarClass1 = Class.forName("cn.javaguide.TargetObject");
通过对象实例instance.getClass()
获取
TargetObject o = new TargetObject();
Class alunbarClass2 = o.getClass();
通过类加载器xxxClassLoader.loadClass()
传入类路径获取
ClassLoader.getSystemClassLoader().loadClass("cn.javaguide.TargetObject");
拿到 Class 对象就可以进行具体的骚操作了!
常用方法
public static void main(String[] args) throws NoSuchMethodException {Class<Object> objectClass = Object.class;Constructor<Object> constructor = objectClass.getConstructor();Class<?>[] interfaces = objectClass.getInterfaces();Annotation[] annotations = objectClass.getAnnotations();Method[] methods = objectClass.getMethods();Field[] fields = objectClass.getFields();}
需要注意的是,在使用反射访问或修改类的私有成员(字段、方法)时,需要使用 setAccessible(true)
方法来取消对访问权限的检查。
反射的原理
JVM使用方法区(或元空间)来存储类的元数据信息,这些元数据包括类的结构、方法、字段、注解等。通过访问方法区中的元数据,反射API可以获取类的信息,并进行相应的操作。
方法区是JVM的一部分,用于存储类的元数据和静态变量。在运行时,JVM会加载类的字节码文件,并将类的元数据存储在方法区中。这些元数据包括类的名称、父类、接口、方法签名、字段信息等。反射API可以通过访问方法区中的元数据来获取类的信息,如获取类的构造函数、方法、字段等。
优缺分析
优点
使得代码更加灵活,比如可以通过反射 + 注解的组合来实现运行时的逻辑处理、动态调用对象方法、动态创建对象、动态代理、动态加载类和资源、动态访问和修改字段属性等
缺点
1、反射的性能较差,所以在对性能要求较高的场景下,反射容易成为系统瓶颈。这是因为反射的代码涉及到了动态解析的类型,导致无法使用 JIT 即时编译器,也就是说,JVM 无法对反射的代码进行优化。
2、反射有一定程度的安全隐患,比如可以越权访问 private 成员,跳过类型检查等。
推荐阅读
一文看懂为什么java反射性能慢、效率低-CSDN博客