反射机制原理
反射是Java在运行时动态获取类信息、操作类属性和方法的能力。核心原理是JVM在类加载时创建Class
对象,该对象包含类的完整结构信息。
关键类:
Class
:类的元数据入口Field
:类的成员变量Method
:类的方法Constructor
:类的构造方法
// 获取Class对象的三种方式
Class<?> clazz1 = String.class; // 类字面常量
Class<?> clazz2 = "Hello".getClass(); // 对象实例
Class<?> clazz3 = Class.forName("java.lang.String"); // 全限定名
内置Class实例和数组生命周期
Class实例生命周期:
类加载时由JVM创建
存储在方法区
生命周期与类加载器绑定
卸载条件:类加载器被GC且无实例引用
数组特殊处理:
// 数组反射示例
int[] intArray = (int[]) Array.newInstance(int.class, 5);
Class<?> arrayClass = intArray.getClass();
System.out.println(arrayClass.getName()); // 输出: [I
System.out.println(arrayClass.getComponentType()); // 输出: int
生命周期特点:
数组类在首次使用时动态创建
类名格式:
[元素类型签名
共享同一个ClassLoader
卸载条件同普通类
反射实战应用:
import java.lang.reflect.*;
class User {
private String name;
private int age;
public User() {}
private User(String name) { this.name = name; }
public void publicMethod() {
System.out.println("Public method called");
}
private String privateMethod(String input) {
return "Processed: " + input;
}
}
public class ReflectionDemo {
public static void main(String[] args) throws Exception {
// 1. 实例化对象
Class<?> userClass = Class.forName("User");
User user = (User) userClass.getDeclaredConstructor().newInstance();
// 2. 访问私有字段
Field nameField = userClass.getDeclaredField("name");
nameField.setAccessible(true); // 突破封装限制
nameField.set(user, "John Doe");
// 3. 调用私有方法
Method privateMethod = userClass.getDeclaredMethod("privateMethod", String.class);
privateMethod.setAccessible(true);
String result = (String) privateMethod.invoke(user, "secret");
System.out.println(result); // 输出: Processed: secret
// 4. 操作私有构造器
Constructor<?> privateConstructor = userClass.getDeclaredConstructor(String.class);
privateConstructor.setAccessible(true);
User user2 = (User) privateConstructor.newInstance("Alice");
// 5. 数组操作
Object array = Array.newInstance(int.class, 3);
Array.set(array, 0, 10);
Array.set(array, 1, 20);
System.out.println(Array.get(array, 1)); // 输出: 20
}
}
反射与设计模式结合
1. 动态代理模式
interface Service {
void serve();
}
class RealService implements Service {
public void serve() {
System.out.println("Real service working");
}
}
class DynamicProxyHandler implements InvocationHandler {
private Object target;
public DynamicProxyHandler(Object target) {
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before method: " + method.getName());
Object result = method.invoke(target, args);
System.out.println("After method: " + method.getName());
return result;
}
}
public class ProxyDemo {
public static void main(String[] args) {
Service realService = new RealService();
Service proxy = (Service) Proxy.newProxyInstance(
Service.class.getClassLoader(),
new Class[]{Service.class},
new DynamicProxyHandler(realService)
);
proxy.serve();
/* 输出:
Before method: serve
Real service working
After method: serve
*/
}
}
灵活工厂模式:
class FlexibleFactory {
public static <T> T create(Class<T> type, Object... args) throws Exception {
Class<?>[] argTypes = new Class[args.length];
for (int i = 0; i < args.length; i++) {
argTypes[i] = args[i].getClass();
}
Constructor<?> constructor = type.getDeclaredConstructor(argTypes);
return type.cast(constructor.newInstance(args));
}
}
// 使用示例
Product product = FlexibleFactory.create(Product.class, "param1", 100);
实践与建议
性能优化:
缓存反射对象(Method/Field)
使用
setAccessible(true)
减少安全检查
private static final Method PRIVATE_METHOD;
static {
try {
PRIVATE_METHOD = TargetClass.class.getDeclaredMethod("methodName");
PRIVATE_METHOD.setAccessible(true);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
安全建议:
限制反射权限(使用SecurityManager)
避免暴露敏感操作接口
应用场景:
框架开发(Spring IOC/AOP)
动态代理(RPC调用)
注解处理器
对象序列化/反序列化
替代方案:
方法句柄(MethodHandle)JDK7+
LambdaMetafactory JDK8+
总结
Java反射机制提供了强大的运行时动态操作能力,但需注意:
谨慎操作私有成员(破坏封装性)
关注性能开销(首次访问较慢)
优先使用标准API替代反射
结合设计模式发挥最大价值
反射是Java高级特性的核心基础,合理使用可使系统更灵活,但过度使用会导致代码可读性降低和维护困难。