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