3

我有以下界面:

interface Foo {
  void bar(String a, int b);
}

我想Foo.bar反射地调用(在 Foo 的实现上)。但是,参数在数组中,我不知道它的大小。

以下不起作用:

void gee(Foo someFoo, Method bar, Object[] args) {
  bar.invoke(someFoo, args);
}

这不起作用,因为args编译器将其作为单个参数进行威胁,并且该数组没有“扩展”为 vararg,而是(内部)包装在另一个具有单个元素的数组中,即

@Test
public void varArgTest() {
  assertTrue(varArgFoo(new Object[] {1, 2}) == 1);
}

private static <T> int varArgFoo(T... arg) {
    return arg.length;
}

在这种情况下,我如何调用Method.invoke()以使数组受到 vararg 的威胁?
或更一般的问题:当参数在数组中时我如何调用可变参数方法我直到运行时才知道数组的大小。

4

2 回答 2

10

可变参数实际上是一个带有一些额外元数据的数组参数。因此,当您使用 时Method.invoke,您需要将数组包装在另一个数组中:

Object[] varargs = new Object[] { 10, 20 };
Object argumentArray = new Object[] { varargs };
method.invoke(target, argumentArray);
于 2012-12-28T16:05:22.713 回答
3

以下不起作用:

是的,它确实。

这不起作用,因为 args 受到编译器作为单个参数的威胁,并且该数组没有“扩展”为 vararg,而是(内部)包装在另一个具有单个元素的数组中,即

使用您提供的代码,数组的元素应该成为可变参数。如果这对您来说没有发生,要么您没有显示您的实际代码,要么是其他错误。

如果您的args变量以某种方式没有数组类型(例如,它是 typed 的Object),那么这可能会发生。但这不是您显示的代码。

或者,如果您有一些未显示的“附加”参数(例如,您正在尝试执行类似的操作bar.invoke(someFoo, firstArg, args);,那么它不会展开args,因为您已经在使用可变参数形式的方法。

于 2012-12-29T02:16:55.590 回答