反射是一种机制,允许在程序运行时检查和修改类、对象、方法和字段的结构和行为。它通过java.lang.reflect包实现。
它允许:
示例:
import java.lang.reflect.Method; public class ReflectionExample { public void greet() { System.out.println("Hello!"); } public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("ReflectionExample"); Object instance = clazz.getDeclaredConstructor().newInstance(); Method method = clazz.getMethod("greet"); method.invoke(instance); // 输出:Hello! } }
优点:
缺点/风险:
是否可以通过反射访问类的private字段和方法,以及后果是什么?
答案: 是的,可以通过Field或Method的setAccessible(true)方法实现:
Field field = clazz.getDeclaredField("privateField"); field.setAccessible(true); field.set(obj, "value");
这会破坏类的封装性,并带来风险:情况变得脆弱,可能出现安全错误,而在新版本的JVM中此类操作可能会受到访问策略的限制。
故事
在一个大型项目中,通过反射自动映射DTO时,类型为"Optional"的字段未被正确考虑,这导致在批量处理数据时出现NullPointerException,因为反射包不区分Optional值和null。
故事
在银行软件中,通过setAccessible(true)访问私有字段以进行序列化。在JVM更新后,行为发生了变化,访问私有字段变得被禁止,重要的序列化功能在生产中突然停止工作。
故事
在ORM框架中,在生成代理对象时忘记在数据模式更改后刷新反射缓存。结果,系统在处理新类字段时产生不可预测的异常,而这些字段未反映在缓存中。