反射是框架(Spring、Hibernate、MyBatis、Jackson)的基石。核心類:Class<T>(類元數據)、Field(字段)、Method(方法)、Constructor<T>(構造器)、Modifier(修飾符)。本文通過 Person 類演示:獲取類信息、動態實例化、屬性讀寫、對象深拷貝。
| 任務 | API | 示例 |
|---|---|---|
| 獲取 Class | Class.forName()、.class、obj.getClass() | Class<?> c = Class.forName("pkg.Person") |
| 獲取所有字段 | c.getDeclaredFields()(含私有) | Field[] fs = c.getDeclaredFields() |
| 獲取所有方法 | c.getDeclaredMethods() | Method[] ms = c.getDeclaredMethods() |
| 暴力訪問私有 | field.setAccessible(true) | 繞過封裝,框架常用 |
| 調用無參構造器 | c.getDeclaredConstructor().newInstance() | 需處理 5 種異常 |
| 調用方法 | method.invoke(obj, args) | 靜態方法傳 null 作為 obj |
| 讀寫字段 | field.get(obj) / field.set(obj, val) | 需 setAccessible(true) |
public static void inspectClass(String className) {
try {
Class<?> c = Class.forName(className);
System.out.println("類名:" + c.getName());
System.out.println("簡單名:" + c.getSimpleName());
System.out.println("包名:" + c.getPackageName());
System.out.println("修飾符:" + Modifier.toString(c.getModifiers()));
System.out.println("父類:" + c.getSuperclass());
System.out.println("介面:" + Arrays.toString(c.getInterfaces()));
System.out.println("--- 字段 ---");
for (Field f : c.getDeclaredFields()) {
System.out.printf(" %s %s %s%n",
Modifier.toString(f.getModifiers()), f.getType().getSimpleName(), f.getName());
}
System.out.println("--- 方法 ---");
for (Method m : c.getDeclaredMethods()) {
System.out.printf(" %s %s %s(%s)%n",
Modifier.toString(m.getModifiers()), m.getReturnType().getSimpleName(),
m.getName(), Arrays.toString(m.getParameterTypes()));
}
} catch (ClassNotFoundException e) { e.printStackTrace(); }
}
@SuppressWarnings("unchecked")
public static <T> T deepCopy(T source) throws Exception {
if (source == null) return null;
Class<?> clazz = source.getClass();
// 1. 創建目標實例(無參構造器)
T target = (T) clazz.getDeclaredConstructor().newInstance();
// 2. 遍歷所有字段
for (Field field : clazz.getDeclaredFields()) {
field.setAccessible(true); // 訪問私有
Object value = field.get(source);
// 3. 遞歸拷貝非基本型別、非不可變類、非集合/Map(簡化版)
if (value != null && !isPrimitiveOrWrapper(field.getType())
&& !field.getType().isArray()) {
value = deepCopy(value); // 遞歸
}
// 數組處理略
field.set(target, value);
}
return target;
}
private static boolean isPrimitiveOrWrapper(Class<?> c) {
return c.isPrimitive() || c == String.class || Number.class.isAssignableFrom(c)
|| c == Boolean.class || c == Character.class || c.isEnum();
}
生產建議:直接用 BeanUtils.copyProperties()(Spring/Apache Commons)、MapStruct(編譯期生成)、Dozer、Jackson 序列化反序列化,勿手寫。
Field/Method/Constructor 對象,或用 MethodHandle(Java 7+)、VarHandle(Java 9+)。setAccessible(true) 受 SecurityManager 限制(模塊化 JDK 9+ 需 --add-opens)。opens pkg to module 或命令行 --add-opens。