java – Reflections IllegalArgumentException原因

前端之家收集整理的这篇文章主要介绍了java – Reflections IllegalArgumentException原因前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
更新 – 使问题更清楚.

在通过反射调用方法时可能会导致ClassCastException异常?

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

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)

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

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)

更新 –
这是我写的尝试重新创建异常的示例代码

接口创建代理类

package my.tests;

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

这是测试类

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

    }
}

我无法理解什么时候我会得到参数类型不匹配,并引起ClassCastException.
我无法重新创建异常,并想知道为什么会这样.在这种情况下,重新创建它的任何工作代码或引用此异常的源代码引用将是很好的

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

解决方法

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

在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(),"doSomething");
}

Reflections类中的invokeMethod方法

public static void invokeMethod(Object obj,Class<?> clazz,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();
    }
}

堆栈跟踪:

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)

我对ClassCastException的解释:

当您第一次调用invokeMethod时,JVM使用较慢的路由,这对程序员来说更容易进行调试(因此它更慢!),因此当传递错误的参数时,它将显示更友好的参数类型不匹配消息.

当你调用invokeMethod很多次(在我的测试中有16次),JVM在运行时生成了一个GeneratedMethodAccessor ***,这样更快,错误检查更少.所以当你传递一个坏的参数时,它会显示一个这么丑的java.lang.ClassCastException@603a3e21消息.

猜你在找的Java相关文章