簡體   English   中英

動態參數反射調用方法

[英]Invoke method by reflection with dynamic parameters

我使用調用類的實例的一些方法method.invoke(instance, args...)的方式,但對於內部的每個方法instance ,作為invoke的Javadoc正確地指出,必須手工指定每個參數。

考慮一下Spring ...如何在HTTP調用期間在幕后的控制器方法中賦予參數價值? (但可以肯定的是,我的想法完全不同...)

我想知道Java中是否有任何方法可以動態地傳遞反射參數(甚至沒有反射參數)而無需單獨指定每個參數。

編輯

實例類的聲明類似於:

public class Something {

    public void doSth(String par1, String par2, Integer par3) {
        //....
    }

    public void doSthElse(String par1, Boolean par2) {
        //....
    }

    public void doSthElseMore(Integer par1) {
        //....
    }

}

我如何調用每種方法:

...
for (Method method : instance.getDeclaredMethods()) {
    Object[] array = //BL: build array of values to pass to the invoke method.
//1. doSth may be new Object[] {"abc", "def", 123}
//2. doSthElse iteration may be new Object[] {"abc", false}
//3. doSthElseMore iteration may be new Object[] {123}
    return method.invoke(instance, array);
}
...

如上所示, Something類( instance )內部的每個方法都有不同數量的參數。

在每次迭代中, array都有不同數量的值傳遞給invoke

實際上,正如@Boris所說,要完成工作,我要做的就是將每個參數轉換為正確的類型。 通過這種方式,Java設法使用正確的參數類型來調用Something類的正確方法。

我的項目是使用VavrjoddVert.x應用程序,但是最后一個return語句顯示了我如何解決。

public Object invokeMethod(Object service, Method method, RoutingContext routingContext) throws Exception {
        MultiMap queryParams = routingContext.queryParams();
        Map<String, String> pathParams = routingContext.pathParams();
        Buffer body = routingContext.getBody();

        // 1. type, 2. name, 3. value
        List<Tuple3<Class<?>, String, Object>> list = List.empty();

        for (Parameter par : method.getParameters()) {
            ParamQuery paramQuery = par.getAnnotation(ParamQuery.class);
            if (paramQuery != null) {
                list = list.push(new Tuple3<Class<?>, String, Object>(par.getType(), paramQuery.value(),
                        queryParams.get(paramQuery.value())));
            }
        }

// TypeConverterManager used to "covnert" each object (String) from the HTTP call to the correct data type
        return method.invoke(service, list.reverse()
                .map(mapper -> TypeConverterManager.lookup(mapper._1()).convert(mapper._3())).toJavaArray());
    }

但是,可以在GitHub上找到該項目

由於我注意到您使用的是Integer而不是int (因此示例中沒有基本參數),因此可以將null發送到所有方法而不會出現任何問題。

因此,您可以創建長度正確的數組,這將適合您的情況。

public static Object[] getParametersArray(Parameter[] param){
    Object[] array = new Object[param.length];
    // create default primitive values based on param[#].getType()
    return array;
}

然后,您要做的就是迭代該方法:

Labo l = new Labo();
for(Method m : Labo.class.getDeclaredMethods()){
    if((m.getModifiers() & Modifier.STATIC) > 0){
        System.out.println("SKIP " + m.getName());
        continue;
    }
    try {
        m.invoke(l, getParametersArray(m.getParameters()));
    } catch (Exception e) {
        e.printStackTrace();
    }
}

注意跳過的靜態方法,主要是因為如果您在包含main方法的方法中運行此方法,則會有一個遞歸調用。

測試了:

public void test(String s){
    System.out.println("test String " + s);
}

public void test2(String s1, String s2){
    System.out.println("test String " + s1 + " | String " + s2);
}

public void test(Integer s){
    System.out.println("test Integer " + s);
}

跳過主要
測試字符串為空
測試整數null
跳過getParametersArray
測試字符串null | 字符串空

注意:如果需要管理一些原始值,則需要獲取參數的類型以提供默認值而不是null

暫無
暫無

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

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