1

I am getting "java.lang.NoSuchMethodException" even though i can see my method in classType.getMethods(); Please help

ShortestPathAlgorithm.java

public class ShortestPathAlgorithm {

    public void show(int[][] graph, int from, int des){

          // some complex code :D 
    }
}

SPATest.java

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);

    }
}

RunWithTimeTrace.java

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 ??

Output :

[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)
1
  • There's a difference between int and Integer, you varargs are been autoboxed to their equivalent types Commented Apr 17, 2016 at 9:06

2 Answers 2

3

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

Sign up to request clarification or add additional context in comments.

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.