反射是 Java「運行時自我檢查與操作」的核心特性,打破編譯期靜態綁定,實現框架級動態性。
核心入口:Class 物件
Class 封裝類型元數據(私有構造器防止外部實例化)。獲取方式:
Class cls1 = Role.class; // 編譯期已知
Class cls2 = Class.forName("yui.Role"); // 運行期字串(全限定名)
實例化
Object obj = cls1.newInstance(); // 僅調用無參構造器
// 等同於 new Role()
構造器操作:Constructor
| 方法 | 範圍 | 返回 |
getConstructors() | public 構造器 | Constructor[] |
getConstructor(Class...) | 指定 public 構造器 | Constructor |
getDeclaredConstructors() | 所有構造器(含 private) | Constructor[] |
getDeclaredConstructor(Class...) | 指定任意構造器 | Constructor |
突破私有限制
Constructor con = cls1.getDeclaredConstructor(String.class);
con.setAccessible(true); // 關鍵:抑制訪問檢查
Object obj = con.newInstance("liyang"); // 帶參實例化
成員變量操作:Field
| 方法 | 範圍 |
getDeclaredField(name) | 任意字段(含 private) |
getDeclaredFields() | 所有字段 |
getField(name) | public 字段 |
getFields() | 所有 public 字段(含繼承) |
讀寫私有字段
Field mem = cls1.getDeclaredField("name");
mem.setAccessible(true);
System.out.println(mem.get(obj)); // 獲取值
mem.set(obj, "newName"); // 設置值
方法操作:Method
| 方法 | 範圍 |
getMethods() | 所有 public 方法(含繼承) |
getMethod(name, Class...) | 指定 public 方法 |
getDeclaredMethods() | 所有聲明方法(含 private) |
getDeclaredMethod(name, Class...) | 指定任意方法 |
調用無參方法
Method m = cls1.getMethod("getName", null);
Object result = m.invoke(obj, null); // 等同 obj.getName()
反射核心價值
- 框架開發:Spring IOC、MyBatis 映射、JSON 序列化皆建立於反射
- 動態代理:JDK Proxy 基於介面反射生成代理類
- 註解處理:編譯期/運行期掃描註解元數據
- 熱加載/插件化:運行期載入未知類
性能與安全提示
- 反射調用比直接調用慢(訪問檢查、JIT 優化受限)
setAccessible(true) 破壞封裝,需謹慎使用
- 模組化系統(JPMS)進一步限制深度反射