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

sku*_*rks 12 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);
}
Run Code Online (Sandbox Code Playgroud)

我得到异常java.lang.IllegalArgumentException:错误的参数数量.怎么了?

Ste*_*n C 12

你需要调用这样的方法:

s.invoke(this, new Object[]{new Object[]{"hi", "there"}});
Run Code Online (Sandbox Code Playgroud)

(...或者在@ 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"版本.或者更准确地说,当且仅当以下情况使用"含糖"解释:

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

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

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


Jon*_*ght 12

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

改变这一行

 s.invoke(this, ex);
Run Code Online (Sandbox Code Playgroud)

对此

 s.invoke(this, (Object)ex);
Run Code Online (Sandbox Code Playgroud)

将工作.

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