I am getting "java.lang.NoSuchMethodException" even though i can see my method in classType.getMethods(); Please help
public class ShortestPathAlgorithm {
public void show(int[][] graph, int from, int des){
// some complex code :D
}
}
public class SPATest {
public static void main(String[] args) {
int graph[][] = {
{0, 1, 5, 4, 0},
{1, 0, 0, 2, 4},
{5, 0, 0, 1, 0},
{4, 2, 1, 0, 1},
{0, 4, 0, 1, 0},
};
Integer from = 1;
Integer des = 2;
RunWithTimeTrace.run(ShortestPathAlgorithm.class, "show", graph, from, des);
}
}
public class RunWithTimeTrace {
public static void run(Class<?> classType, String methodName, Object... paramValues ){
try{
Object o = classType.newInstance();
int n = paramValues.length;
Class<?>[] arr = new Class[n];
for(int i=0; i < n; i++){
arr[i] = paramValues[i].getClass();
}
Method[] declaredMethods = classType.getMethods();
System.out.println(Arrays.toString(declaredMethods));
System.out.println("------------------------");
Method method = classType.getDeclaredMethod(methodName, arr);
long s = System.currentTimeMillis();
method.invoke(o, paramValues);
long t = System.currentTimeMillis();
System.out.println("Time Taken : " + (t - s));
}catch(Exception e){
e.printStackTrace();
}
}
}
I am able to see my method in getMethods but not in reflection. Why ??
[public void demo.ds.graph.main.ShortestPathAlgorithm.show(int[][],int,int), public final void java.lang.Object.wait() throws java.lang.InterruptedException, public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException, public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException, public boolean java.lang.Object.equals(java.lang.Object), public java.lang.String java.lang.Object.toString(), public native int java.lang.Object.hashCode(), public final native java.lang.Class java.lang.Object.getClass(), public final native void java.lang.Object.notify(), public final native void java.lang.Object.notifyAll()]
------------------------
java.lang.NoSuchMethodException: demo.ds.graph.main.ShortestPathAlgorithm.show([[I, java.lang.Integer, java.lang.Integer)
at java.lang.Class.getDeclaredMethod(Class.java:2130)
at demo.ds.graph.test.RunWithTimeTrace.run(RunWithTimeTrace.java:23)
at demo.ds.graph.test.SPATest.main(SPATest.java:20)
Basically, you parameter values are been autoboxed to their Object
equivalents ( int
to Integer
) which means that the reflection API is looking for a method with the formal parameters of Integer[][], Integer, Integer
, which it obviously can't find
If, however, I change your run
method to something like...
public static void run(Class<?> classType, String methodName, Object[] paramValues, Class[] types) {
try {
Object o = classType.newInstance();
int n = paramValues.length;
Method[] declaredMethods = classType.getMethods();
System.out.println(Arrays.toString(declaredMethods));
System.out.println("------------------------");
Method method = classType.getDeclaredMethod(methodName, types);
long s = System.currentTimeMillis();
method.invoke(o, paramValues);
long t = System.currentTimeMillis();
System.out.println("Time Taken : " + (t - s));
} catch (Exception e) {
e.printStackTrace();
}
}
And then use
run(ShortestPathAlgorithm.class, "show", new Object[]{graph, from, des}, new Class[]{int[][].class, int.class, int.class});
it works
Me, personally, I'd wrap a lot of this up into a class of sometype, so you can specify not only the parameter value, but it's type in a single call...
Runner runner = new Runner(ShortestPathAlgorithm.class)
.execute("show")
.withParameter(int[][].class, graph)
.withParameter(int.class, from)
.withParameter(int.class, des);
runner.run();
The "main" reason I'd approach it this way, is in the past, I've wasted a lot of time chasing down which parameter/value pair broke, and it's much easier to read and comprehend using a builder pattern in this way, but that's just me.
I'd also be looking for just about any other solution other then using reflection, it has it's place and can do a lot, but it's not really a reliable, long term solution, especially when you need to refactor code
The problem is that your method needs int
types (primitives) but you're searching for a method using Integer
type (non primitive), which are two different things and so it cannot be found. The reason why you're searching for non primitives is the types of from
and des
. Try changing them to int
, probably the signature of RunWithTimeTrace.run
has to be changed as well to fit the parameters.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.