反射 API (java.lang.reflect) 允許程序在運行時檢查類結構、讀寫字段、調用方法、甚至實例化對象,無需編譯時依賴目標類。這種動態性支援插件架構、序列化框架、依賴注入等場景。
Class clazz = MyClass.class;Class.forName("com.example.MyClass") — 觸發類載入與初始化。Class[] types = {String.class, String.class};
Constructor cons = TwoString.class.getConstructor(types);
TwoString ts = cons.newInstance(new Object[]{"a", "b"});
或使用 clazz.newInstance() 快速調用無參構造器(需為 public)。
Field field = obj.getClass().getDeclaredField("name");
field.setAccessible(true); // 繞過訪問控制
int value = field.getInt(obj) + 1;
field.setInt(obj, value);
getDeclaredField 可訪問私有字段,getField 僅限 public 且包含繼承字段。
Method method = clazz.getMethod("setCount", int.class);
method.invoke(obj, new Integer(42));
參數與返回值自動進行基本類型與包裝類型轉換。
使用 java.lang.reflect.Array 靜態方法創建、讀寫陣列,如動態擴容:
Class compType = array.getClass().getComponentType();
Object grown = Array.newInstance(compType, newSize);
System.arraycopy(array, 0, grown, 0, Math.min(Array.getLength(array), newSize));
反射默認遵守 Java 訪問修飾符。AccessibleObject.setAccessible(true) 可關閉檢查,但受 SecurityManager 限制。若啟用安全管理器且無權限,將拋出 SecurityException。
測試環境:1GHz PIII,Linux,循環 1000 萬次。結果(對數坐標):
newInstance() 慢 2~12 倍;Array.newInstance 慢約 2 倍。Sun 1.4.1 對反射調用優化顯著,但仍遠慢於直接代碼。
下一部分將展示一個利用反射自動映射命令行參數到對象字段的實用庫,體現反射在「配置映射」場景的優勢。