反射(Reflection) 允许程序在运行时动态:
核心类:
Class>
:类的元数据Constructor>
:构造函数Method
:方法Field
:字段Modifier
:访问修饰符解析工具// 方式1:通过类名.class(最安全,性能最好)
Class> clazz1 = String.class;
// 方式2:通过对象.getClass()
String str = "Hello";
Class> clazz2 = str.getClass();
// 方式3:通过Class.forName()(最灵活,需处理异常)
Class> clazz3 = Class.forName("java.lang.String");
// 无参构造创建对象
Class> clazz = Class.forName("com.example.User");
Object user1 = clazz.newInstance(); // 已过时,推荐使用下面的方法
// 有参构造创建对象(更安全)
Constructor> constructor = clazz.getConstructor(String.class, int.class);
Object user2 = constructor.newInstance("张三", 25);
class Calculator {
public int add(int a, int b) {
return a + b;
}
}
// 反射调用方法
Class> clazz = Calculator.class;
Object calculator = clazz.newInstance();
Method addMethod = clazz.getMethod("add", int.class, int.class);
int result = (int) addMethod.invoke(calculator, 3, 5); // 输出: 8
class Person {
private String name = "默认姓名";
}
// 反射访问私有字段
Person person = new Person();
Class> clazz = person.getClass();
Field field = clazz.getDeclaredField("name");
field.setAccessible(true); // 关键:解除私有访问限制
// 读取字段值
String nameValue = (String) field.get(person); // "默认姓名"
// 修改字段值
field.set(person, "李四");
System.out.println(person.getName()); // 假设有getter方法,输出: "李四"
List list = new ArrayList<>();
list.add("合法数据");
// 通过反射插入非String类型
Method addMethod = list.getClass().getMethod("add", Object.class);
addMethod.invoke(list, 100); // 插入整数
System.out.println(list); // 输出: [合法数据, 100]
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
String value();
}
@MyAnnotation("测试注解")
class MyClass {}
// 读取类上的注解
Class> clazz = MyClass.class;
MyAnnotation annotation = clazz.getAnnotation(MyAnnotation.class);
System.out.println(annotation.value()); // 输出: 测试注解
interface Animal {
void speak();
}
class Dog implements Animal {
public void speak() {
System.out.println("汪汪!");
}
}
// 动态代理实现
Animal proxy = (Animal) Proxy.newProxyInstance(
Dog.class.getClassLoader(),
new Class[]{Animal.class},
(obj, method, args) -> {
System.out.println("方法调用前日志");
return method.invoke(new Dog(), args);
}
);
proxy.speak(); // 输出: 方法调用前日志 → 汪汪!
反射调用比直接调用慢100倍以上,优化方案:
缓存反射对象:重复使用的 Method
/Field
存入Map
private static Map methodCache = new HashMap<>();
public static Method getCachedMethod(Class> clazz, String methodName, Class>... paramTypes) {
String key = clazz.getName() + "#" + methodName;
return methodCache.computeIfAbsent(key, k -> clazz.getMethod(methodName, paramTypes));
}
使用MethodHandle
(Java 7+):接近直接调用的性能
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodHandle handle = lookup.findVirtual(String.class, "length", MethodType.methodType(int.class));
int length = (int) handle.invokeExact("Hello"); // 输出: 5
避免重复安全检查:通过setAccessible(true)
禁用访问检查
Field field = clazz.getDeclaredField("secret");
field.setAccessible(true); // 后续访问不再检查权限
public static Map objectToMap(Object obj) throws Exception {
Map map = new HashMap<>();
Class> clazz = obj.getClass();
// 获取所有字段(包括私有)
for (Field field : clazz.getDeclaredFields()) {
field.setAccessible(true);
map.put(field.getName(), field.get(obj));
}
return map;
}
// 测试
class User {
private String name = "张三";
public int age = 25;
}
User user = new User();
Map map = objectToMap(user);
System.out.println(map); // 输出: {name=张三, age=25}