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 に「展開」されず、単一の要素を持つもう 1 つの配列に (内部的に) ラップされるため、これは機能しません。

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

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

Method.invoke()この場合、配列がvarargとして脅かされるようにするにはどうすればよいですか?
または、より一般的な質問: 引数が配列にあるときに vararg メソッドを呼び出すにはどうすればよいですか? 実行時まで配列のサイズがわかりません。

4

2 に答える 2

10

vararg パラメーターは、実際には少し追加のメタデータを持つ配列パラメーターです。したがって、 を使用するときは、配列を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に「拡張」されず、単一の要素を持つもう1つの配列に(内部的に)ラップされるため、これは機能しません。

提示したコードでは、配列の要素がvarargs引数になるはずです。それが起こらない場合は、実際のコードが表示されていないか、他の何かが間違っています。

どういうわけかあなたのargs変数が配列型を持っていない場合(例えばそれが型付けされている場合Object)、それは起こる可能性があります。しかし、それはあなたが示しているコードではありません。

または、表示していない「追加の」引数がある場合(たとえば、のようなことをしようとしている場合、すでにvarargs形式のメソッドを使用しているため、bar.invoke(someFoo, firstArg, args);展開されません。args

于 2012-12-29T02:16:55.590 に答える