Javareflection:getMethod(String方法,Object .class)无法正常工作

我有以下代码:

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

我得到exceptionjava.lang.IllegalArgumentException:错误的参数数量。 怎么了?

你需要调用这样的方法:

 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})语法糖xxx(new T2[]{arg1, arg2, arg3})

在这种情况下,您尝试使用具有相同数组基类型的另一个varadic方法调用varadic方法,并且对代码有多种可能的解释。

当对varadic调用有两种可能的解释时,Java 假定您正在尝试使用“unsugared”版本的调用而不是“sugared”版本。 或者更准确地说, 当且仅当以下情况使用“含糖”解释:

  • 实际参数的数量不等于forms参数的数量,
  • 最后一个实际参数是与最后一个forms参数的(数组)类型兼容的赋值。

如果您有兴趣,可以在第15.12.4.2节的JLS中指定此行为。

所以…我的解决方案通过强制非varadic解释和显式构造所需的数组来工作。 @ Jon的解决方案通过强制正确的 varadic解释来工作。

这里的问题是Method.invoke采用的变量参数( Object... )。

改变这一行

  s.invoke(this, ex); 

对此

  s.invoke(this, (Object)ex); 

将工作。

在后台, Object...作为Object[]传递。 Java看到你的Object[]并选择不将它包装在另一个Object[] 。 通过转换为Object ,它现在只是看到它并恢复其正常的包装行为 – 与其他答案手动执行的操作相同。

您可以使用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