[英]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
類的正確方法。
我的項目是使用Vavr
和jodd
的Vert.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.