【问题标题】:Java reflection: getMethod(String method, Object[].class) not workingJava 反射:getMethod(String method, Object[].class) 不起作用
【发布时间】:2011-07-24 04:17:58
【问题描述】:

我有以下代码:

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: wrong number of arguments。怎么了?

【问题讨论】:

  • 你从哪里得到异常?在对getMethodinvoke 的调用中?
  • 很明显这不是真正的代码,因为有错别字(例如getClass -> getClass())。也许真正的代码在某些方面有所不同?
  • 欧内斯特,我已编辑为 user679573 添加括号。除此之外,代码是有效的,所以我觉得这是一个合理的步骤。 (主要是评论,以免别人误解你的评论。)

标签: java reflection


【解决方案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

【讨论】:

    【解决方案2】:

    你需要这样调用方法:

    s.invoke(this, new Object[]{new Object[]{"hi", "there"}});
    

    (...或使用@Jon 的答案中的替代方法。)

    您当前代码失败的原因与 Java 中实现可变方法的方式有关。本质上,T1 xxx(T2... args)T1 xxx(T2[] args) 的语法糖。当你调用方法时,xxx(arg1, arg2, arg3)xxx(new T2[]{arg1, arg2, arg3}) 的语法糖。

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

    当可变参数调用有两种可能的解释时,Java 假定您正在尝试使用调用的“未加糖”版本而不是“加糖”版本。或者更准确地说,使用“糖化”解释当且仅当

    • 实参个数不等于形参个数,
    • 最后一个实参与最后一个形参的(数组)类型不兼容。

    如果您有兴趣,此行为在 JLS 中的 15.12.4.2 部分中指定。

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

    【讨论】:

    • 如果实际参数较少,也会使用加糖版本 - 然后它会创建一个空数组。这适用于s.invoke(this)
    【解决方案3】:

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

    改变这一行

     s.invoke(this, ex);
    

    到这里

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

    会起作用的。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-21
      • 1970-01-01
      • 2013-01-20
      • 1970-01-01
      相关资源
      最近更新 更多