簡體   English   中英

帶有子類參數的Java getMethod

[英]Java getMethod with subclass parameter

我正在編寫一個使用反射來動態查找和調用方法的庫。 給定一個對象、一個方法名稱和一個參數列表,我需要調用給定的方法,就好像方法調用是在代碼中顯式編寫的一樣。

我一直在使用以下方法,該方法在大多數情況下都有效:

static void callMethod(Object receiver, String methodName, Object[] params) {
    Class<?>[] paramTypes = new Class<?>[params.length];
    for (int i = 0; i < param.length; i++) {
        paramTypes[i] = params[i].getClass();
    }
    receiver.getClass().getMethod(methodName, paramTypes).invoke(receiver, params);
}

但是,當其中一個參數是該方法支持的類型之一的子類時,反射 API 將NoSuchMethodException 例如,如果接收者的類定義了testMethod(Foo) ,則以下操作失敗:

receiver.getClass().getMethod("testMethod", FooSubclass.class).invoke(receiver, new FooSubclass());

即使這有效:

receiver.testMethod(new FooSubclass());

我該如何解決? 如果方法調用是硬編碼的,則沒有問題 - 編譯器只是使用重載算法來選擇要使用的最佳適用方法。 但是,它不適用於反射,這正是我所需要的。

提前致謝!

它比您開始時的要長一點,但這可以滿足您的要求......此外還有一點 - 例如, callMethod(receiver, "voidMethod") 其中 voidMethod 不帶任何參數也有效。

static void callMethod(Object receiver,
      String methodName, Object... params) {
  if (receiver == null || methodName == null) {
    return;
  }
  Class<?> cls = receiver.getClass();
  Method[] methods = cls.getMethods();
  Method toInvoke = null;
  methodLoop: for (Method method : methods) {
    if (!methodName.equals(method.getName())) {
      continue;
    }
    Class<?>[] paramTypes = method.getParameterTypes();
    if (params == null && paramTypes == null) {
      toInvoke = method;
      break;
    } else if (params == null || paramTypes == null
        || paramTypes.length != params.length) {
      continue;
    }

    for (int i = 0; i < params.length; ++i) {
      if (!paramTypes[i].isAssignableFrom(params[i].getClass())) {
        continue methodLoop;
      }
    }
    toInvoke = method;
  }
  if (toInvoke != null) {
    try {
      toInvoke.invoke(receiver, params);
    } catch (Exception t) {
      t.printStackTrace();
    }
  }
}

receiver.testMethod(new FooSubclass());
even though this works:

如果您的testMethod函數具有FooSuperClass類型的參數:

 public void testMethod(FooSuperClass object){}

然后,當您嘗試使用反射獲取匹配方法時: getClass().getMethod("testMethod", FooSubclass.class)將導致NoSuchMethodException 因為這個getMethod(String name, Class<?>... parameterTypes函數返回一個Method對象,它是一個具有給定name的公共成員方法,其中parameterTypes參數是標識方法形式參數類型的 Class 對象數組。實際上有沒有用簽名testMedthod(FooSubClass object)聲明這樣的方法,因為函數的FooSuperClass參類型是FooSuperClass 。所以,正確的調用是:

receiver.getClass().getMethod("testMethod", FooSuperClass.class)
                        .invoke(receiver, new FooSubclass());

或者,通過調用SubClass.class.getSuperClass()傳遞超類,如下所示:

receiver.getClass().getMethod("testMethod", FooSubClass.class.getSuperclass())
                            .invoke(receiver, new FooSubclass());

或者,將方法簽名更改為: public void testMethod(FooSubClass object){}然后像現在一樣調用:

receiver.getClass().getMethod("testMethod", FooSubclass.class)
                         .invoke(receiver, new FooSubclass());

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM