[英]using reflection to invoke methods which takes different parameters
我在类中有两个方法,一个接受Comparable[]
作为参数并返回一个Boolean
值。另一个方法接受一个Comparable[]
和一个int
值,返回一个Boolean
。我试着写一些方法来调用方法反射..
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class MethodCalling {
private static Class classTocall;
private static Method methodTocall;
public MethodCalling(String classname){
super();
try {
this.classTocall = Class.forName(classname);
} catch (ClassNotFoundException e) {
System.out.println("failed to get class!!");
e.printStackTrace();
}
}
public void setMethod(String method,Class...args){
try {
this.methodTocall = this.classTocall.getMethod(method, args);
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
public Object callMethod(Object...args){
Object result = null;
try {
if(this.methodTocall != null){
result = this.methodTocall.invoke(null, new Object[]{args});
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return result;
}
public static void main(String[] args) {
String[] a = new String[]{"H","E","L","L","O"};
MethodCalling mc = new MethodCalling("SizeChecker");
mc.setMethod("isTooBig", Comparable[].class);
Boolean result1 = (Boolean) mc.callMethod(a);
System.out.println("too big="+result1);
mc.setMethod("isCorrectLength",Comparable[].class,int.class);
Boolean result2 = (Boolean) mc.callMethod(a,5);
System.out.println("length is 5="+result2);
}
}
class SizeChecker{
public static boolean isTooBig(Comparable[] a){
return a.length > 10;
}
public static boolean isCorrectLength(Comparable[] a,int x){
return a.length == x;
}
}
当参数(它是一个String[]
)被包装在Object[]
时,第一个方法调用(即isTooBig()
)工作。但是这对于接受String[]
和int的下一个方法调用失败了。 。
我该如何纠正?
在callMethod
, args
已经是一个数组。 你不需要包装它:
result = this.methodTocall.invoke(null, args);
在main
,警告(在Eclipse中)足够清楚:
String[]
类型的参数应该显式地转换为Object[]
以便从MethodCalling
类型调用varargs方法callMethod(Object...)
。 也可以将其转换为Object
以进行varargs调用
或者javac
给出的警告
警告:非varargs调用varargs方法,最后一个参数的参数类型不精确;
Boolean result1 = (Boolean) mc.callMethod(a); ^
转换为
Object
以进行varargs调用转换为
Object[]
以进行非varargs调用并禁止此警告
解:
Boolean result1 = (Boolean) mc.callMethod((Object) a);
这里的问题就在于此
result = this.methodTocall.invoke(null, new Object[]{args});
当你将参数传递给方法时,你将它们包装在另一个Object []中,这是一个不必要的,当args
包含多个参数时(比如第二个方法调用中的字符串和int),将这些参数隐藏在Object
数组中,使它们显示为一个参数。 这就是你得到错误的原因。
使用以下更改解决此问题:
result = this.methodTocall.invoke(null, args);
然后将主方法更改为:
String[] a = new String[]{"H","E","L","L","O"};
MethodCalling mc = new MethodCalling("wat.SizeChecker");
mc.setMethod("isTooBig", Comparable[].class);
/* change here: place the single parameter into a parameter array */
Boolean result1 = (Boolean) mc.callMethod(new Object[]{a});
System.out.println("too big="+result1);
mc.setMethod("isCorrectLength",Comparable[].class, int.class);
/* since the callMethod accepts varargs, these are automatically placed in an Object[] */
Boolean result2 = (Boolean) mc.callMethod(a, 5);
System.out.println("length is 5="+result2);
容易哥们,问题(2)
1。 您将String数组作为Object数组传递给callMethod()
函数,而您需要将String数组作为一个参数传递,但它将作为5个参数传递,简单只需替换此代码
Boolean result1 = (Boolean) mc.callMethod(a);
对此
Boolean result1 = (Boolean) mc.callMethod(new Object[]{args});
这可以确保整个数组作为一个参数传递。
2。 另一个问题,你只用一个参数调用方法(this this.methodTocall.invoke(null, new Object[]{args})
),事实上第二次调用你把所有的参数作为一个参数用Object[]{args}
并调用该方法。 所以改变这一行
result = this.methodTocall.invoke(null, new Object[]{args});
有了这个
result = this.methodTocall.invoke(null, args);
您需要将String数组声明为对象:
Object a = new String[] { "H", "E", "L", "L", "O" };
并直接使用invoke
方法的args
参数:
result = this.methodTocall.invoke(null, args);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.