Java反射:getMethod(String方法,Object [] .class)无法正常工作

时间:2011-03-28 03:06:35

标签: java reflection

我有以下代码:

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:错误的参数数量。怎么了?

3 个答案:

答案 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