反射是 Java 程式語言的一項核心特性,它賦予了執行中的 Java 程式「自省」的能力。透過反射,程式可以在運行時檢查自身的結構,動態獲取類的成員資訊(如類名、方法、欄位、建構子等),並能直接操作物件的內部屬性與方法。這項能力在 Pascal、C 或 C++ 等語言中並不存在,使得 Java 在動態載入、框架開發、工具構建等領域具備獨特優勢。JavaBean 便是反射的典型應用場景之一,各類開發工具透過反射動態載入組件並可視化操作其屬性。
以下程式碼展示如何利用反射列出指定類別的所有宣告方法:
import java.lang.reflect.*;
public class DumpMethods {
public static void main(String[] args) {
try {
Class> c = Class.forName(args[0]);
Method[] methods = c.getDeclaredMethods();
for (Method m : methods) {
System.out.println(m.toString());
}
} catch (Throwable e) {
System.err.println(e);
}
}
}
執行指令:java DumpMethods java.util.Stack
輸出結果將包含 Stack 類別的所有方法簽名、修飾符與回傳型別。核心步驟在於 Class.forName() 載入類別,再呼叫 getDeclaredMethods() 取得方法陣列。
Class.forName("全限定類名")、類名.class 或 基本型別包裝類.TYPE(如 Integer.TYPE)獲取 java.lang.Class 實例。getDeclaredMethods()、getDeclaredFields()、getDeclaredConstructors() 等方法獲取方法、欄位、建構子陣列。Method、Field、Constructor 等反射 API 進行動態調用、賦值、實例化等操作。instanceof 操作符Class.isInstance(obj) 可判斷物件是否為該類別或其子類的實例,實現動態型別檢查。
透過 Method 物件可取得方法名稱、宣告類別、參數型別陣列、拋出異常型別、回傳型別等詳細資訊。getDeclaredMethods() 僅獲取當前類宣告的方法(含 private),getMethods() 則包含繼承的 public 方法。
使用 Constructor 類別,可根據參數型別動態尋找建構子並透過 newInstance() 創建新物件,實現運行時動態實例化。
Field 類別提供 getXxx() / setXxx() 方法,支援依名稱動態存取物件欄位,甚至可修改 private 欄位(需先呼叫 setAccessible(true))。
透過 getMethod(name, paramTypes) 取得 Method 物件,再呼叫 invoke(obj, args) 執行,適用於方法名在運行時才確定的場景(如 JavaBean 屬性存取、事件分發)。
java.lang.reflect.Array 類別提供靜態方法 newInstance()、get()、setXxx(),支援動態建立多維陣列並操作元素,陣列元件型別在編譯期可未知。
Java 反射機制打破了編譯期的靜態綁定,讓程式擁有極高的動態性與擴展性。它是 Spring、Hibernate 等主流框架實現依賴注入、ORM、AOP 等核心功能的基石。掌握反射,不僅能深入理解框架原理,更能在需要動態載入、插件化架構、通用工具開發時遊刃有餘。但需注意:反射涉及安全檢查、效能開銷較大,生產環境應謹慎使用並做好快取與異常處理。