Java 反射機制是 Java 語言的一項核心特性,它允許程式在執行期動態地獲取類的內部資訊(如建構子、屬性、方法),並能實例化物件、呼叫方法、存取欄位。這種「編譯期不知類型,執行期動態綁定」的能力,是 Spring、Hibernate 等主流框架實現解耦、依賴注入、ORM 映射的基石。本文將系統梳理反射的核心 API、基本操作步驟、程式碼實戰示例,並以 Hibernate 為例剖析其在實際框架中的應用場景。
Java 反射 API 主要位於 java.lang.reflect 套件中,核心由四個類組成,它們共同構成了類結構的完整視圖:
| 方法 | 說明 |
|---|---|
getConstructor(Class[] params) | 獲取指定參數類型的 public 建構子 |
getConstructors() | 獲取所有 public 建構子 |
getDeclaredConstructor(Class[] params) | 獲取指定參數類型的建構子(含 private/protected) |
getDeclaredConstructors() | 獲取所有宣告的建構子(不受修飾符限制) |
| 方法 | 說明 |
|---|---|
getField(String name) | 獲取指定名稱的 public 欄位 |
getFields() | 獲取所有 public 欄位 |
getDeclaredField(String name) | 獲取指定名稱的宣告欄位(含私有) |
getDeclaredFields() | 獲取所有宣告的欄位 |
| 方法 | 說明 |
|---|---|
getMethod(String name, Class[] params) | 獲取指定參數類型的 public 方法 |
getMethods() | 獲取所有 public 方法(含繼承) |
getDeclaredMethod(String name, Class[] params) | 獲取指定參數類型的宣告方法(含私有) |
getDeclaredMethods() | 獲取所有宣告的方法 |
Class.forName("全限定類名") —— 最常用,支援動態載入類名.class —— 編譯期已知類型時使用物件.getClass() —— 已有實例時使用getDeclaredMethod、getDeclaredField 等方法,並對私有成員呼叫 setAccessible(true) 破壞封裝。constructor.newInstance(args)、method.invoke(obj, args)、field.set(obj, value) 等。import java.lang.reflect.*;
public class ConstructorDemo {
public ConstructorDemo() {}
public ConstructorDemo(int a, int b) {
System.out.println("a=" + a + ", b=" + b);
}
public static void main(String[] args) throws Exception {
Class> cls = Class.forName("ConstructorDemo");
Class>[] paramTypes = {int.class, int.class};
Constructor> ct = cls.getConstructor(paramTypes);
Object instance = ct.newInstance(37, 47);
}
}
import java.lang.reflect.*;
public class FieldDemo {
private double d;
public static void main(String[] args) throws Exception {
Class> cls = Class.forName("FieldDemo");
Field fld = cls.getDeclaredField("d");
fld.setAccessible(true); // 關鍵:暴力反射
FieldDemo obj = new FieldDemo();
System.out.println("修改前 d = " + fld.getDouble(obj));
fld.setDouble(obj, 12.34);
System.out.println("修改後 d = " + fld.getDouble(obj));
}
}
import java.lang.reflect.*;
public class MethodDemo {
public int add(int a, int b) { return a + b; }
public static void main(String[] args) throws Exception {
Class> cls = Class.forName("MethodDemo");
Method meth = cls.getMethod("add", int.class, int.class);
MethodDemo obj = new MethodDemo();
Object result = meth.invoke(obj, 37, 47);
System.out.println("結果: " + result); // 輸出 84
}
}
Hibernate 作為經典的 ORM 框架,其核心任務是將 Java 物件自動持久化到資料庫。由於框架編譯期完全不知道使用者會定義哪些實體類,必須依靠反射在執行期動態分析類結構。
PreparedStatement,獲得 ResultSet。String[] props 及其類型。Class 物件:Class> clazz = entity.getClass();。set + 屬性名首字母大寫。ResultSet 取值:rs.getInt(i)、rs.getString(i) 等。method.invoke(entity, value)。這就是「無須硬編碼即可操作任意類」的反射威力。缺點是效能較直接呼叫略低,且破壞封裝需注意安全性,但框架層面通常可透過快取 Method 物件、使用 MethodHandle 或字節碼生成(如 CGLIB、ByteBuddy)優化。
Java 反射機制賦予了語言極大的動態性,是框架開發的利器。掌握 Class、Constructor、Field、Method 四大核心類及其常用 API,理解「獲取 Class → 獲取成員 → 執行操作」三步驟,並能結合實際場景(如 ORM、依賴注入、動態代理)靈活運用,是進階 Java 開發者的必備技能。