我有以下代码:
public void myMethod(Object... args) {
System.out.println("this is myMethod");
}
public void invokeMyMethod() {
Method s = this.getClass().getMethod("myMethod", Object[].class);
Object[] ex = new Object[2];
ex[0] = "hi";
ex[1] = "there";
s.invoke(this, ex);
}
我收到异常java.lang.IllegalArgumentException:错误的参数数量。怎么了?
答案 0 :(得分:12)
你需要调用这样的方法:
s.invoke(this, new Object[]{new Object[]{"hi", "there"}});
(...或在@ Jon的答案中使用替代方案。)
当前代码失败的原因与Java中实现varadic方法的方式有关。基本上,T1 xxx(T2... args)
是T1 xxx(T2[] args)
的语法糖。当你调用方法时,xxx(arg1, arg2, arg3)
是xxx(new T2[]{arg1, arg2, arg3})
的语法糖。
在这种情况下,您尝试使用具有相同数组基本类型的另一个varadic方法调用varadic方法,并且对代码有多种可能的解释。
当对varadic调用有两种可能的解释时,Java 假定您正在尝试使用“unsugared”版本的调用而不是“sugared”版本。或者更确切地说,“含糖”解释仅在时使用:
如果您有兴趣,可以在15.12.4.2部分的JLS中指定此行为。 所以...我的解决方案通过强制非varadic解释并显式构造所需的数组来工作。 @ Jon的解决方案通过强制正确的 varadic解释来工作。
答案 1 :(得分:12)
这里的问题是Object...
采用的变量参数(Method.invoke
)。
更改此行
s.invoke(this, ex);
到这个
s.invoke(this, (Object)ex);
会奏效。
在后台,Object...
作为Object[]
传递。 Java看到你的Object[]
并选择不将其包装在另一个Object[]
中。通过转换为Object
,它现在只能看到并恢复其正常的包装行为 - 与其他答案手动执行的操作相同。
答案 2 :(得分:1)
您可以使用dp4j命令行来回答您的问题:
$ javac -cp ../dp4j-1.2-SNAPSHOT-jar-with-dependencies.jar -All -Averbose=true MyClass.java
MyClass.java:7: Note:
public class MyClass {
public MyClass() {
super();
}
public void myMethod(Object... args) {
System.out.println("this is myMethod");
}
@com.dp4j.Reflect()
public void invokeMyMethod() throws java.lang.ClassNotFoundException, java.lang.NoSuchFieldException, java.lang.IllegalAccessException, java.lang.NoSuchMethodException, java.lang.reflect.InvocationTargetException, java.lang.IllegalArgumentException {
final java.lang.reflect.Method myMethodWithArrayMethod = Class.forName("MyClass").getDeclaredMethod("myMethod", .java.lang.Object[].class);
myMethodWithArrayMethod.setAccessible(true);
myMethodWithArrayMethod.invoke(this, new .java.lang.Object[1][]{new .java.lang.Object[2][]{"hi", "there"}});
}
public static void main(String... args) throws Exception {
new MyClass().invokeMyMethod();
}
}
public void invokeMyMethod() {
^
$ java MyClass
this is myMethod