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

Java 反射動態調用方法通用工具類封裝與參數類型適配實戰

     編輯:Java 相關知識

基礎版:標準反射調用

public Object invokeMethod(String className, String methodName, Object[] args) throws Exception {
    Class<?> ownerClass = Class.forName(className);
    Object owner = ownerClass.newInstance();
    Class<?>[] argsClass = new Class[args.length];
    for (int i = 0; i < args.length; i++) {
        argsClass[i] = args[i].getClass();
    }
    Method method = ownerClass.getMethod(methodName, argsClass);
    return method.invoke(owner, args);
}

實戰難點:實參類型與形參類型不匹配

場景:Struts 1.x Action 方法簽名為:

public ActionForward execute(ActionMapping mapping, ActionForm form,
                             HttpServletRequest request, HttpServletResponse response)

實際運行時,request 是 org.apache.catalina.connector.RequestFacade,實現了 HttpServletRequest 介面。若直接傳入實例,getMethod 會因參數類型不匹配(RequestFacade.class != HttpServletRequest.class)拋出 NoSuchMethodException。

解決方案:參數類型手動修正

for (int i = 0; i < args.length; i++) {
    if (i == 3) { // response 位於第 4 個參數
        argsClass[i] = HttpServletResponse.class;
    } else {
        argsClass[i] = args[i].getClass();
    }
}

同理,若框架注入的是介面類型,需手動將實參類型替換為介面類型,確保 getMethod 能匹配到聲明簽名。

進階封裝:智能參數適配器

public class ReflectionInvoker {
    private static final Map<Class<?>, Class<?>> INTERFACE_MAP = new HashMap<>();
    static {
        INTERFACE_MAP.put(org.apache.catalina.connector.RequestFacade.class, HttpServletRequest.class);
        INTERFACE_MAP.put(org.apache.catalina.connector.ResponseFacade.class, HttpServletResponse.class);
        // 可擴展更多容器實現類
    }

    public static Object invoke(Object target, String methodName, Object... args) throws Exception {
        Class<?>[] paramTypes = new Class[args.length];
        for (int i = 0; i < args.length; i++) {
            Class<?> actual = args[i].getClass();
            // 自動映射至介面
            paramTypes[i] = INTERFACE_MAP.getOrDefault(actual, actual);
        }
        Method method = target.getClass().getMethod(methodName, paramTypes);
        return method.invoke(target, args);
    }
}

最佳實踐建議

  1. 緩存 Method 物件:高頻調用時避免重複 getMethod 開銷。
  2. 處理基本類型:int.class vs Integer.class 需手動轉換,ClassUtils.primitiveToWrapper 可輔助。
  3. 異常包裝:將反射異常轉為業務異常,屏蔽底層細節。
  4. 安全檢查:setAccessible(true) 可訪問私有方法,但需權衡安全性。

總結

反射動態調用的核心難點在於參數類型匹配。通過建立「容器實現類 → 標準介面」的映射表,或在特定位置強制指定介面類型,可優雅解決此問題,構建通用、健壯的反射調用工具。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved