java 反射 IllegalArgumentException 导致

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16042591/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 21:43:01  来源:igfitidea点击:

Reflections IllegalArgumentException causes

javareflectionclasscastexceptionillegalargumentexception

提问by Aditya

UPDATE- To make the question clearer.

更新- 使问题更清楚。

What is the possible cause of getting a ClassCastException while calling a method via reflections?

通过反射调用方法时获得 ClassCastException 的可能原因是什么?

I got the following stacktrace as a part of my application while trying to invoke a method via reflections.

在尝试通过反射调用方法时,我将以下堆栈跟踪作为我的应用程序的一部分。

java.lang.IllegalArgumentException: java.lang.ClassCastException@21fea1fv
    at sun.reflect.GeneratedMethodAccessor332.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com..... 
    (remaining is my method stack trace)

I tried an example class and passed various arguments of different types to it, but i always get a this exception.

我尝试了一个示例类并将不同类型的各种参数传递给它,但我总是得到这个异常。

java.lang.IllegalArgumentException: argument type mismatch
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)

UPDATE -Here is the sample code i wrote to try recreating the exception

更新 -这是我为尝试重新创建异常而编写的示例代码

Interface to create proxy class

创建代理类的接口

package my.tests;

public interface ReflectionsInterface { 
    public abstract void doSomething();
}

This is the test class

这是测试类

package my.tests;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class Reflections implements ReflectionsInterface {

    public static void main(String[] args) {
        Reflections reflections = new Reflections();
        ReflectionsInterface reflectionsProxy = reflections.createProxy(ReflectionsInterface.class);
        invokeMethod(reflectionsProxy, "doSomething", null);
    }

    public <T> T createProxy(Class<T> entityInterface) {
        EntityInvocationHandler eih = new EntityInvocationHandler(this);
        T cast = entityInterface.cast(Proxy.newProxyInstance(
                entityInterface.getClassLoader(), new Class[]{entityInterface}, eih));
        return cast;
    }

    public static void invokeMethod(Object obj, String methodName, Object... args) {
        Method[] methods = obj.getClass().getMethods();
        try {
            for (Method method : methods) {
                if (method.getName().equals(methodName)) {
                    method.invoke(obj, args);
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void doSomething() {
        System.out.println("woo");
    }

    private final static class EntityInvocationHandler implements InvocationHandler,
            ReflectionsInterface {

        private Reflections reflectionObj;

        public EntityInvocationHandler(Reflections reflectionObj) {
            super();
            this.reflectionObj = reflectionObj;
        }

        @Override
        public void doSomething() {
            reflectionObj.doSomething();
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Object invoke = method.invoke(this, args);
            return invoke;
        }

    }
}

I am unable to understand the when i would get argument type mismatchand the ClassCastExceptionwould be caused. I am not able to re-create the exception and would like to know why it comes. Any working code that re-created it, or a source code reference throwing this exception in this case will be good

我无法理解何时会出现参数类型不匹配以及会导致ClassCastException我无法重新创建异常并想知道它为什么会出现。重新创建它的任何工作代码,或在这种情况下抛出此异常的源代码参考都很好

I have gone through the Method.class javadocs and source code, i am not able to figure out why this error comes.

我已经浏览了 Method.class javadocs 和源代码,我无法弄清楚为什么会出现这个错误。

回答by johnchen902

I had recreated the ClassCastExceptionby modifing your example code: Invoke invokeMethodwith a correct argument 10000 times, and then invoke it with wrong a wrong one.

ClassCastException通过修改您的示例代码重新创建了:invokeMethod使用正确的参数调用10000 次,然后使用错误的参数调用它。

The mainmethod in the Reflectionsclass

类中的main方法Reflections

public static void main(String[] args) {
    Reflections reflections = new Reflections();
    ReflectionsInterface reflectionsProxy = reflections
            .createProxy(ReflectionsInterface.class);
    for (int i = 0; i < 10000; i++)
        invokeMethod(reflectionsProxy, ReflectionsInterface.class,
                "doSomething");

    invokeMethod(new Object(), ReflectionsInterface.class, "doSomething");
}

The invokeMethodmethod in the Reflectionsclass

类中的invokeMethod方法Reflections

public static void invokeMethod(Object obj, Class<?> clazz,
        String methodName, Object... args) {
    Method[] methods = clazz.getMethods();
    try {
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                method.invoke(obj, args);
                break;
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Stack Trace:

堆栈跟踪:

java.lang.IllegalArgumentException: java.lang.ClassCastException@603a3e21
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.twbbs.pccprogram.Reflections.invokeMethod(Reflections.java:33)
    at org.twbbs.pccprogram.Reflections.main(Reflections.java:16)

My explanation of the ClassCastException:

我的解释ClassCastException

When you invoke invokeMethodfor the first time, JVM use a slower route, which is easier for programmers to debug (so it's slower!), so it will show a more friendly argument type mismatchmessage when you passes a bad argument.

当你invokeMethod第一次调用时,JVM 使用较慢的路由,这对于程序员来说更容易调试(所以它更慢!),所以argument type mismatch当你传递一个错误的参数时它会显示更友好的消息。

When you invoke invokeMethodfor a lot of times (16 times are enough in my tests), JVM generated a GeneratedMethodAccessor***in runtime, which is faster, with less error checking. So it will show such an ugly java.lang.ClassCastException@603a3e21message when you passes a bad argument.

当您invokeMethod多次调用时(在我的测试中 16 次就足够了),JVM 会GeneratedMethodAccessor***在运行时生成一个,速度更快,错误检查更少。所以java.lang.ClassCastException@603a3e21当你传递一个错误的论点时,它会显示出如此丑陋的信息。

回答by Jon Skeet

Well this is the problem:

嗯,这就是问题所在:

reflections.invokeMethod("doInt", 1L);

You're calling doInt, but you're passing a longvalue. So reflection is trying to cast a Longto an Integer, which is invalid.

您正在调用doInt,但您正在传递一个long值。所以反射试图将 a 转换Long为 an Integer,这是无效的。

I suspect you meant:

我怀疑你的意思是:

reflections.invokeMethod("doLong", 1L);

回答by mki

I have a bit modify your code to reproduce this error :

我对您的代码进行了一些修改以重现此错误:

java.lang.IllegalArgumentException: argument type mismatch

Here is the interface

这是界面

public interface ReflectionsInterface
{
  public abstract void doSomething1(Integer i);
  public abstract void doSomething2(String s);
}

Add the method in class Reflections and EntityInvocationHandler in order to compile. Then add this method in your main(). Execute and I produce the error runtime.

在类 Reflections 和 EntityInvocationHandler 中添加该方法以进行编译。然后在你的 main() 中添加这个方法。执行,我产生错误运行时。

invokeMethod(reflectionsProxy, "doSomething1", "1");

I have tried to get un ClassCastException but I didn't succeed. It occurs probably in your original code because there are more objects and an invalid type is passed to the method. Add logs and try to debug to isolated the ClassCastException.

我试图得到 un ClassCastException 但我没有成功。它可能发生在您的原始代码中,因为有更多的对象并且将无效类型传递给该方法。添加日志并尝试调试以隔离 ClassCastException。