晓知识: 如何理解反射
Java 反射的概念
Java 反射(Reflection)是一种在运行时动态获取类信息、操作类属性和方法的机制。通过反射,可以在程序运行时检查类、接口、字段和方法,而不需要在编译时知道这些类的具体定义。反射的核心是 java.lang.reflect
包,提供了 Class
、Method
、Field
、Constructor
等类来实现动态操作。
反射的核心类
Class
:表示类或接口,是反射的入口。可以通过Class
对象获取类的构造方法、字段、方法等信息。Field
:表示类的成员变量,可以动态获取或修改字段的值(包括私有字段)。Method
:表示类的方法,可以动态调用方法(包括私有方法)。Constructor
:表示类的构造方法,可以动态创建对象实例。
反射的基本用法
获取 Class 对象
// 方式1:通过类名.class
Class<?> clazz = String.class;// 方式2:通过对象.getClass()
String str = "Hello";
Class<?> clazz = str.getClass();// 方式3:通过 Class.forName("全限定类名")
Class<?> clazz = Class.forName("java.lang.String");
创建对象实例
Class<?> clazz = Class.forName("java.lang.String");
// 调用无参构造方法
String str = (String) clazz.newInstance(); // 已过时,推荐使用 getConstructor()
// 使用 Constructor
Constructor<?> constructor = clazz.getConstructor();
String str = (String) constructor.newInstance();
访问字段
Class<?> clazz = Person.class;
Field field = clazz.getDeclaredField("name"); // 获取字段(包括私有字段)
field.setAccessible(true); // 允许访问私有字段
Person person = new Person();
field.set(person, "Alice"); // 设置字段值
String name = (String) field.get(person); // 获取字段值
调用方法
Class<?> clazz = Person.class;
Method method = clazz.getDeclaredMethod("sayHello", String.class); // 获取方法
method.setAccessible(true); // 允许调用私有方法
Person person = new Person();
Object result = method.invoke(person, "World"); // 调用方法
System.out.println(result); // 输出方法返回值
反射的应用场景
- 动态加载类:在运行时加载并操作未知的类(如插件化开发)。
- 框架开发:Spring、Hibernate 等框架利用反射实现依赖注入、ORM 映射等功能。
- 测试工具:JUnit 等测试框架通过反射调用测试方法。
- 反编译工具:分析类的结构,获取类的方法、字段等信息。
反射的优缺点
- 优点:灵活性高,可以实现动态编程,适合框架和工具开发。
- 缺点:性能较低(比直接调用慢),破坏封装性(可以访问私有成员),可能引发安全问题。
注意事项
- 反射操作私有成员时需调用
setAccessible(true)
,但可能违反封装原则。 - 反射会降低性能,应避免在频繁调用的代码中使用。
- 反射可能引发
ClassNotFoundException
、NoSuchMethodException
等异常,需妥善处理。