微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

以字符串数组为参数的调用方法会导致IllegalArgumentException

如何解决以字符串数组为参数的调用方法会导致IllegalArgumentException

我正在使用运行时反射来加载包含以下两个方法的类:

public static void foo(int[] args)
{
    System.out.print("foo invoked: ");
    for(int arg : args)
        System.out.print(arg + " ");
    
    System.out.println();
}

public static void bar(String[] args)
{
    System.out.print("bar invoked: ");
    for(String arg : args)
        System.out.print(arg + " ");
    
    System.out.println();
}

(除了一个采用int数组,而另一个采用字符串数组的相同方法

然后,我尝试像这样调用两个方法

    int[] intArr = {1,2,3};
    clazz.getmethod("foo",int[].class).invoke(null,intArr);

    String[] strArr = {"1","2","3"};
    clazz.getmethod("bar",String[].class).invoke(null,strArr); //Exception

(此处“ clazz”是这两个方法所在的类,我在运行时已将其加载)

第一次调用不会引起异常,并且会输出预期的输出,但是第二次调用会引发以下异常:

Exception in thread "main" java.lang.IllegalArgumentException: wrong number of arguments
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at ReflectionTests.main(ReflectionTests.java:63)

这是为什么?

解决方法

观察到invoke具有以下签名:

public Object invoke(Object obj,Object... args)

args是一个可变参数,允许您将调用的方法的每个参数作为invoke的参数进行传递,例如

someStaticMethod.invoke(null,param1,param2,param3);

将致电:

someStaticMethod(param1,param3);

另一方面,args的类型实际上只是Object[],并且由于数组是协变的,因此存在从String[]Object[]的转换。>

因此,当您将String[]中的strArr传递给invoke时,可能会发生以下两种情况之一:

  • strArr被转换为Object[],并且每个String被视为要调用的方法的参数。
  • 整个strArr被视为要调用的方法的参数之一,就像非数组类型一样。

编译器恰好偏爱第一个(请参见here。请注意,可变域调用的优先级最低),因此实际上是在传递参数"1",{{1} },"2",而不是一个单个"3"

另一方面,String[]不能直接转换为int[],因为Object[]是原始的,因此编译器只能选择上面的第二个选项。

强制第二个选项的一种方法是强制转换为int

Object

另一种方法是创建另一个用clazz.getMethod("bar",String[].class).invoke(null,(Object)strArr); 包装的Object[]

String[]
,

您必须将将要执行该方法的初始化对象作为invoke()方法的第一个参数传递。

Foo foo =新的Foo(); 方法method = clazz.getMethod(“ method”);

method.invoke(foo,params []);

invoke()需要对象执行该方法。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。