Reputation: 8467
I have two methods in a class ,one takes a Comparable[]
as parameter and returns a Boolean
value.The other method takes a Comparable[]
and an int
value ,returning a Boolean
.I tried to write some methods to invoke the methods using reflection..
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;
}
}
The first method invocation( ie, isTooBig()
) works when the argument (which is a String[]
) is wrapped in an Object[]
.. But this fails for the next method invocation which takes a String[]
and an int..
How do I correct this?
Upvotes: 1
Views: 7243
Reputation:
Easy buddy, the problems(2)
1 . you pass the String array as Object array to the callMethod()
function, while you need to pass the String array as one argument, but it will passed as 5 arguments, simple just replace this code
Boolean result1 = (Boolean) mc.callMethod(a);
to this
Boolean result1 = (Boolean) mc.callMethod(new Object[]{args});
this ensures you the whole array will passed as one argument.
2 . and another issue, you call the method (this this.methodTocall.invoke(null, new Object[]{args})
) with just one argument again, in fact with second call you put all the arguments as one argument with Object[]{args}
and invoke the method.
so change this line
result = this.methodTocall.invoke(null, new Object[]{args});
with this
result = this.methodTocall.invoke(null, args);
Upvotes: 1
Reputation: 9601
In callMethod
, args
is already an array. You don't need to wrap it:
result = this.methodTocall.invoke(null, args);
In main
, the warning (in Eclipse) is clear enough:
The argument of type
String[]
should explicitly be cast toObject[]
for the invocation of the varargs methodcallMethod(Object...)
from typeMethodCalling
. It could alternatively be cast toObject
for a varargs invocation
Or the warning given by javac
warning: non-varargs call of varargs method with inexact argument type for last parameter;
Boolean result1 = (Boolean) mc.callMethod(a); ^
cast to
Object
for a varargs callcast to
Object[]
for a non-varargs call and to suppress this warning
Solution:
Boolean result1 = (Boolean) mc.callMethod((Object) a);
Upvotes: 2
Reputation: 11934
The problem here is in the line
result = this.methodTocall.invoke(null, new Object[]{args});
When you pass arguments to the method, you wrap them in another Object[], which is a) unnecessary and, when args
contains multiple arguments (like the string and the int from your second method call), hides those arguments in the Object
array, making them appear as one parameter. That is why you get the error.
Solve it by using the following changes:
result = this.methodTocall.invoke(null, args);
Then change your main method to this:
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);
Upvotes: 1
Reputation: 48807
You need to declare your String array as an object:
Object a = new String[] { "H", "E", "L", "L", "O" };
And to use directly the args
arguments for the invoke
method:
result = this.methodTocall.invoke(null, args);
Upvotes: 0