Java反射是运行时动态操作类、方法、字段的底层能力,需手动处理ClassNotFoundException、IllegalAccessException、InvocationTargetException三类异常;Class.forName()触发类初始化而ClassLoader.loadClass()不触发;调用私有方法须setAccessible(true);可修改非编译期常量的final字段;反射牺牲类型安全与JVM优化。

Java反射机制不是语法糖,而是运行时动态操作类、方法、字段的底层能力;它不改变编译逻辑,但会绕过编译期检查,因此必须手动处理 ClassNotFoundException、IllegalAccessException、InvocationTargetException 这三类核心异常。
如何通过类名字符串获取 Class 对象
最常用也最容易出错的是 Class.forName() 和 ClassLoader.loadClass() 的区别:前者会触发类的初始化(执行 static 块),后者只加载不初始化。多数场景下应优先用 Class.forName(),尤其涉及依赖静态资源或单例初始化时。
- 使用
Class.forName("com.example.User")时,包路径必须完整且大小写敏感;拼错会抛ClassNotFoundException - 若类在模块路径(Java 9+)中未导出,即使路径正确也会失败,需检查
module-info.java中是否含exports - 避免用
MyClass.class替代字符串加载——这属于编译期绑定,失去“动态”意义
调用私有方法与绕过访问检查
反射调用私有方法的关键是先调用 setAccessible(true),否则会抛 IllegalAccessException;但 JVM 安全管理器(如某些容器环境)可能禁止此操作,此时会抛 SecurityException。
Method method = clazz.getDeclaredMethod("parseInternal", String.class);
method.setAccessible(true); // 必须在 invoke 前调用
Object result = method.invoke(instance, "input");
-
getDeclaredMethod()只查本类声明的方法,不包含父类;要查继承链上的方法,得用getMethod(),但它只识别 public 方法 - 参数类型必须严格匹配:传
int.class却用Integer.class会导致NoSuchMethodException - 调用静态方法时,
invoke()第一个参数传null即可,无需实例
修改 final 字段值的可行性与限制
反射可以修改 final 字段,但仅限于运行时常量(compile-time constant)以外的字段;例如 public static final String NAME = "abc" 在编译期就被内联,反射修改无效。
图书《网页制作与PHP语言应用》,由武汉大学出版社于2006出版,该书为普通高等院校网络传播系列教材之一,主要阐述了网页制作的基础知识与实践,以及PHP语言在网络传播中的应用。该书内容涉及:HTML基础知识、PHP的基本语法、PHP程序中的常用函数、数据库软件MySQL的基本操作、网页加密和身份验证、动态生成图像、MySQL与多媒体素材库的建设等。
立即学习“Java免费学习笔记(深入)”;
- 修改前需先调用
field.setAccessible(true),再用Field.set() - 对
static final字段,还需先用Unsafe或反射修改modifiers字段,移除Modifier.FINAL标志位(JDK 12+ 限制更严) - 修改基本类型包装类(如
Integer)的static final值,可能因缓存机制(如Integer.valueOf(127))导致部分调用仍返回旧值
反射的代价不只是性能损耗(JIT 很难优化反射调用),更在于它把类型安全、封装边界、甚至 JVM 优化策略都交由开发者手工维护——一个没 catch 的 InvocationTargetException 就可能让整条链路静默失败。








