反射是 Java 語言在執行期檢查、修改類別結構與行為的能力。編譯期僅有 .class 位元碼,執行期 JVM 將其載入為 java.lang.Class 物件,反射 API 即操作此元資料物件,實現:
| 類別 | 用途 | 常用方法 |
|---|---|---|
java.lang.Class | 類別元資料入口 | forName(), getFields(), getMethods(), getConstructors(), newInstance() |
java.lang.reflect.Constructor | 建構子操作 | newInstance(), setAccessible(true) |
java.lang.reflect.Field | 屬性操作 | get(obj), set(obj, val), getModifiers() |
java.lang.reflect.Method | 方法操作 | invoke(obj, args), getParameterTypes() |
java.lang.reflect.Modifier | 修飾符解析 | isPublic(), isStatic(), toString(mod) |
public class Employee {
private String name;
public Employee() {}
public Employee(String name) { this.name = name; }
public void work() { System.out.println(name + " 在工作"); }
}
// 方式 1:Class.forName("全類名") — 最常用,支援動態類名
Class> c1 = Class.forName("Employee");
// 方式 2:類字面常量 — 編譯期已知類型,效能最佳
Class> c2 = Employee.class;
// 方式 3:實例.getClass() — 執行期類型(多型場景)
Employee e = new Employee();
Class> c3 = e.getClass();
// 驗證:同一 JVM 中同一類只有一個 Class 物件
System.out.println(c1 == c2); // true
System.out.println(c2 == c3); // true
class A {
static { System.out.println("A 初始化"); }
}
// Class.forName("A") → 觸發靜態區塊(主動使用)
// A.class → 不觸發(被動引用)
// new A() → 觸發
public class ReflectDemo {
public static void main(String[] args) throws Exception {
Class> clazz = Class.forName("Employee");
// 1. 調用有參建構子
Constructor> ctor = clazz.getDeclaredConstructor(String.class);
Employee emp = (Employee) ctor.newInstance("張三");
// 2. 存取私有欄位
Field nameField = clazz.getDeclaredField("name");
nameField.setAccessible(true); // 破壞封裝
System.out.println("原名:" + nameField.get(emp)); // 張三
nameField.set(emp, "李四");
System.out.println("新名:" + nameField.get(emp)); // 李四
// 3. 呼叫方法
Method work = clazz.getMethod("work");
work.invoke(emp); // 輸出:李四 在工作
}
}
Method/Field/Constructor 物件,或用 MethodHandle (Java 7+) / VarHandle (Java 9+)。setAccessible(true) 受 SecurityManager 限制;模組化 (Java 9+) 需 opens package to module 或命令行 --add-opens。@Controller、@Autowired、@Transactional 實現 AOPProxy.newProxyInstance() + InvocationHandler (Spring AOP 底層)TypeToken (Gson) / ParameterizedType 解決類型擦除ServiceLoader) 載入實作類反射是 Java 動態特性的基石,賦予框架「約定優於配置」的魔力。理解 Class 載入時機、三大核心元件 (Field/Method/Constructor) 協作、setAccessible 邊界,是進階 Java 工程師的必修課。實務上:框架寫反射,業務用框架。