简体   繁体   English

Java Reflection getMethod给出了Exception

[英]Java Reflection getMethod giving Exception

I am getting "java.lang.NoSuchMethodException" even though i can see my method in classType.getMethods(); 我得到“java.lang.NoSuchMethodException”,即使我可以在classType.getMethods()中看到我的方法; Please help 请帮忙

ShortestPathAlgorithm.java ShortestPathAlgorithm.java

public class ShortestPathAlgorithm {

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

          // some complex code :D 
    }
}

SPATest.java 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 RunWithTimeTrace.java

public class RunWithTimeTrace { 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. 我可以在getMethods中看到我的方法,但不能在反射中看到。 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)

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 基本上,您的参数值已被自动装箱到它们的Object等价物( intInteger ),这意味着反射API正在寻找一个带有Integer[][], Integer, Integer形式参数的方法,它显然无法找到

If, however, I change your run method to something like... 但是,如果我将run方法更改为...

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... 我个人而言,我将很多内容包装成一个sometype类,所以你不仅可以指定参数值,而且可以在一次调用中输入...

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. 问题是你的方法需要int类型(原语),但你正在使用Integer类型(非原始)搜索一个方法,这是两个不同的东西,所以无法找到它。 The reason why you're searching for non primitives is the types of from and des . 你在搜索非原语的原因是fromdes的类型。 Try changing them to int , probably the signature of RunWithTimeTrace.run has to be changed as well to fit the parameters. 尝试将它们更改为int ,可能还必须更改RunWithTimeTrace.run的签名以适合参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM