首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java 反射機制核心原理與實戰:Class 對象、動態加載與性能考量

     編輯:Java 綜合教學

Java 反射機制核心原理與實戰:Class 對象、動態加載與性能考量

反射是 Java 動態性的基石,允許運行時檢查類結構、創建實例、調用方法、訪問字段(含 private)。框架開發、依賴注入、序列化、動態代理均建立於此。

核心概念:Class 對象

每個類在 JVM 中僅有一個 Class<T> 實例,由類加載器加載 .class 文件時創建。它是反射的入口,包含類的完整元數據:修飾符、父類、接口、字段、方法、構造器、註解等。

// Class 對象類型示例
Class c1 = String.class;        // 具體類型
Class c2 = Class.forName("java.lang.String"); // 未知類型用通配符
Class c3 = int[].class;          // 數組類型
Class c4 = void.class;            // 基本類型 void

三種獲取 Class 對象的方式

  1. 實例 .getClass():Class c = "abc".getClass(); — 需要實例,運行時確定。
  2. Class.forName("全限定名"):Class c = Class.forName("com.test.MyObject"); — 僅需字符串名,支援動態加載,**會觸發類初始化**(執行 static 塊)。
  3. 類字面常量 .class:Class c = MyObject.class; — 編譯期檢查,**不觸發類初始化**,性能最佳,推薦優先使用。

反射常見操作示例

Class clazz = User.class;
// 1. 創建實例(需無參構造器)
User user = (User) clazz.getDeclaredConstructor().newInstance();

// 2. 訪問私有字段
Field nameField = clazz.getDeclaredField("name");
nameField.setAccessible(true); // 破壞封裝
nameField.set(user, "Tom");

// 3. 調用私有方法
Method sayHi = clazz.getDeclaredMethod("sayHi", String.class);
sayHi.setAccessible(true);
sayHi.invoke(user, "Hello");

// 4. 掃描註解
if (clazz.isAnnotationPresent(Table.class)) { ... }

性能與安全注意事項

  • 性能開銷:反射調用比直接調用慢 10-100 倍(JIT 難優化、訪問檢查、裝箱拆箱)。熱點路徑請緩存 Method/Field/Constructor 對象,或使用 MethodHandle / VarHandle(Java 9+)。
  • 安全風險:setAccessible(true) 可繞過封裝,模塊化系統中需 opens 導出包。
  • 模塊化限制:Java 9+ 強封裝,內部 API 需 --add-opens 才能反射訪問。

應用場景

  • 框架通用邏輯:Spring IOC 掃描 @Component、MyBatis 映射 ResultSet
  • 動態代理:JDK Proxy、CGLIB、字節碼生成庫
  • 插件系統/熱插拔:運行時加載外部 Jar 並實例化
  • 測試工具:Mockito、JUnit 通過反射注入 Mock、訪問私有狀態
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved