Java反射
Java 反射
反射允许程序在运行时检查类、构造器、字段、方法和注解,并动态创建对象或调用方法。
获取 Class 对象
代码块收起展开
Class<User> type1 = User.class;
Class<?> type2 = user.getClass();
Class<?> type3 = Class.forName("com.example.User");类型.class:最直接,不触发额外查找。object.getClass():从已有对象获取实际运行时类型。Class.forName():按全限定名加载类,默认会触发类初始化。
检查与调用成员
代码块收起展开
Class<?> type = Class.forName("com.example.User");
Constructor<?> constructor = type.getDeclaredConstructor(String.class);
Object user = constructor.newInstance("Gilbert");
Method method = type.getDeclaredMethod("getName");
Object result = method.invoke(user);getMethod():查找public方法,包含继承成员。getDeclaredMethod():查找当前类声明的方法,不要求public。getField()与getDeclaredField()的区别相同。- 目标方法抛出的异常会被包装为
InvocationTargetException,真实异常通过getCause()获取。
访问控制与模块边界
setAccessible(true) 可以尝试绕过 Java 语言层访问检查,但在 Java 9+ 模块系统中可能受到强封装限制。不要把反射作为常规封装逃生口;框架需要深度反射时,应明确模块开放范围。
适用场景
- 依赖注入与 IoC 容器。
- ORM、序列化与反序列化。
- 注解处理和测试框架。
- 插件系统与运行时适配。
普通业务代码能通过接口、多态或工厂解决时,优先普通调用:它有编译期类型检查,更容易重构,也更易阅读。
反射、MethodHandle 与代码生成
MethodHandle 是更强类型、可组合的动态调用机制,常用于 JVM 语言和高性能框架。高频动态调用还可能使用字节码生成。选择顺序通常是:普通多态优先,其次反射;只有性能测量证明反射是瓶颈时,再考虑 MethodHandle 或代码生成。