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

Java 反射機制實戰:動態呼叫方法完整範例解析

     編輯:Java 程式設計入門

Java 反射機制允許程式在執行期動態獲取類資訊、建立實例、呼叫方法,是 Spring、Hibernate 等主流框架的核心基石。本文透過一個完整可執行的範例,詳細演示如何使用反射 API 動態呼叫帶參數的方法,並解析關鍵步驟與常見陷阱。

核心程式碼範例

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflexTest {
    public static void main(String[] args) 
            throws ClassNotFoundException, NoSuchMethodException, 
                   IllegalAccessException, IllegalArgumentException, 
                   InvocationTargetException, InstantiationException {

        // 1. 定義目標方法的參數型別陣列(對應 Demo.getSome(String, Integer, String))
        Class[] paramTypes = new Class[3];
        paramTypes[0] = String.class;
        paramTypes[1] = Integer.class;
        paramTypes[2] = String.class;

        // 2. 獲取目標方法物件:類.getDeclaredMethod(方法名, 參數型別...)
        Method method = Demo.class.getDeclaredMethod("getSome", paramTypes);

        // 3. 準備實際參數值陣列(順序、型別必須與 paramTypes 完全對應)
        Object[] argsValues = new Object[3];
        argsValues[0] = "pp";      // String
        argsValues[1] = 4;         // Integer (自動裝箱)
        argsValues[2] = "3";       // String

        // 4. 動態呼叫方法:method.invoke(實例物件, 參數陣列)
        // 此處 Demo.class.newInstance() 等同於 new Demo(),需無參建構子
        method.invoke(Demo.class.newInstance(), argsValues);
    }
}

// 目標類別
class Demo {
    public void getSome(String name, Integer year, String age) {
        System.out.println("name is :" + name + "; age is :" + age + "; year is :" + year);
    }
}

關鍵步驟深度解析

1. 獲取 Method 物件的兩種途徑

  • getMethod(String name, Class... parameterTypes):僅能獲取 public 方法(含繼承)。
  • getDeclaredMethod(String name, Class... parameterTypes):可獲取類自行宣告的所有方法(含 private/protected),但不含繼承方法。範例使用此方式更通用。

2. 參數型別匹配規則

paramTypes 必須與目標方法簽名完全一致:

  • 基本型別用 Xxx.TYPE(如 int.class / Integer.TYPE)
  • 引用型別直接用 Xxx.class
  • 順序不可錯誤,否則拋出 NoSuchMethodException

3. invoke() 參數詳解

Object invoke(Object obj, Object... args)
  • obj:方法接收者。靜態方法傳 null,實例方法傳實例物件。
  • args:可變長參數陣列,自動處理基本型別裝箱/拆箱。
  • 返回值:方法有返回值則返回具體物件,void 方法返回 null。

4. 異常處理最佳實踐

反射呼叫會拋出多種受檢異常,建議採用「捕獲轉換」策略:

try {
    method.invoke(instance, args);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
    // InvocationTargetException 內部包裹了目標方法真實拋出的異常
    Throwable cause = e.getCause();
    throw new RuntimeException("反射呼叫失敗: " + cause.getMessage(), cause);
}

進階應用場景

  • 框架開發:依賴注入(DI)、AOP 切面攔截、ORM 映射
  • 熱插拔/外掛系統:動態載入類並呼叫約定介面
  • 測試工具:單元測試框架自動發現並執行 @Test 方法
  • 序列化/反序列化:Jackson、Gson 等庫透過反射讀寫私有欄位

效能與安全性提醒

  • 效能開銷:反射比直接呼叫慢 10-100 倍(JIT 難以優化),高頻熱路徑建議快取 Method 物件或使用 MethodHandle/VarHandle。
  • 存取權限:呼叫私有方法前需 method.setAccessible(true),但在 Java 9+ 模組化系統下可能受限,需在 module-info.java 中 opens 相關套件。
  • 安全管理器:舊版 SecurityManager 可限制反射權限,現代應用較少使用。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved