Java 反射機制允許程式在運行時動態獲取類的完整結構資訊(構造器、欄位、方法、註解、繼承關係等),並能實例化物件、呼叫方法、存取欄位。簡單說:已知「類名」或「物件」,即可還原「類的全部定義」。
Class 物件(Class.forName()、.class、obj.getClass())。Class 提供的 API 讀取構造器、方法、欄位等元資料並操作。// 1. 類全名字串(最常用,支援動態載入)
Class> cls1 = Class.forName("com.example.Person");
// 2. 類字面常量(編譯期可檢查)
Class cls2 = Person.class;
// 3. 實例物件
Person p = new Person();
Class> cls3 = p.getClass();
// 4. 字串物件(注意:這會得到 String.class,非目標類)
String className = "com.example.Person";
Class> cls4 = className.getClass(); // 結果是 java.lang.String
| 分類 | 代表方法 | 說明 |
|---|---|---|
| 構造器 | getConstructor(s)、getDeclaredConstructor(s) | 前者僅 public,後者含私有;可用 setAccessible(true) 破壞封裝 |
| 方法 | getMethod(s)、getDeclaredMethod(s) | 同構造器邏輯;invoke(obj, args) 執行呼叫 |
| 欄位 | getField(s)、getDeclaredField(s) | 前者含繼承 public,後者含私有;set(obj, value) 賦值 |
| 類元資料 | getSuperclass()、getInterfaces()、getAnnotations() | 繼承鏈、實現介面、運行時註解 |
| 判斷特性 | isInterface()、isEnum()、isPrimitive()、isAnonymousClass() | 快速識別類型特徵 |
Class> cls = Class.forName("com.example.Person");
// 取私有無參構造器
Constructor> cst = cls.getDeclaredConstructor();
cst.setAccessible(true);
Object obj = cst.newInstance();
// 取私有方法 setGender(Gender)
Method m = cls.getDeclaredMethod("setGender", Gender.class);
m.setAccessible(true);
m.invoke(obj, Gender.MALE);
class UserDao extends BaseDao{} // 運行時可解析出 User、Long Type superType = UserDao.class.getGenericSuperclass(); ParameterizedType pType = (ParameterizedType) superType; Type[] actualTypes = pType.getActualTypeArguments(); // [User, Long]
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface ApiDoc { String value(); }
class Controller {
@ApiDoc("用戶登入")
public void login() {}
}
// 掃描
for (Method m : Controller.class.getDeclaredMethods()) {
if (m.isAnnotationPresent(ApiDoc.class)) {
System.out.println(m.getAnnotation(ApiDoc.class).value());
}
}
MethodHandle 或緩存 Method/Field 物件緩解。setAccessible(true) 可能被 SecurityManager 禁止;模組化(JPMS)下需 opens 導出封裝。Type 系統(ParameterizedType、TypeVariable)配合繼承結構推導。反射是框架(Spring、Hibernate、Jackson、MyBatis 等)實現「約定優於配置」、「依賴注入」、「ORM 映射」的基石。掌握 Class、Constructor、Method、Field 四大核心類及其 Declared 與非 Declared 差異,配合 setAccessible 與泛型 Type 體系,即可駕馭動態編程的強大威力。