簡単な質問ですが、このコードをどのように機能させるのですか?
public class T {
public static void main(String[] args) throws Exception {
new T().m();
}
public // as mentioned by Bozho
void foo(String... s) {
System.err.println(s[0]);
}
void m() throws Exception {
String[] a = new String[]{"hello", "kitty"};
System.err.println(a.getClass());
Method m = getClass().getMethod("foo", a.getClass());
m.invoke(this, (Object[]) a);
}
}
出力:
class [Ljava.lang.String;
Exception in thread "main" Java.lang.IllegalArgumentException: wrong number of arguments
at Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at Sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.Java:39)
at Sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.Java:25)
at Java.lang.reflect.Method.invoke(Method.Java:597)
_Test.class.getDeclaredMethod("foo", String[].class);
_
動作します。問題は、getMethod(..)
がpublic
メソッドのみを検索することです。 javadocから:
このClassオブジェクトによって表されるクラスまたはインターフェイスの指定されたパブリックメンバーメソッドを反映するMethodオブジェクトを返します。
pdate:メソッドを正常に取得したら、次を使用して呼び出すことができます。
_m.invoke(this, new Object[] {new String[] {"a", "s", "d"}});
_
つまり、-1つの要素を持つ新しいObject
配列を作成します-String
配列。変数名を使用すると、次のようになります。
_m.invoke(this, new Object[] {a});
_
//編集する前に:
あなたの問題は、getMethod
がpublic
メンバーを探すという事実です。
_Class.getMethod
_ (私の強調)から:
このClassオブジェクトによって表されるクラスまたはインターフェイスの指定されたpublicメンバーメソッドを反映する
Method
オブジェクトを返します
したがって、2つのオプションがあります。
public void foo(String... s)
を作成し、getMethod
を使用しますgetDeclaredMethod
を使用してください_getField/s
_と_getDeclaredField/s
_および_getConstructor/s
_と_getDeclaredConstructor/s
_にも同じ違いがあることに注意してください。
// invoke
問題
これは特に厄介ですが、invoke(Object obj, Object... args)
は_Object[]
_にキャスト可能であるため、参照型の配列を唯一の引数として渡す必要がある場合は注意が必要です。代わりに、_new Object[1]
_でラップする必要があります。
できるよ:
_m.invoke(this, new Object[] {a}); // Bohzo's solution
_
これはvarargメカニズムをバイパスします。より簡潔に行うこともできます。
_m.invoke(this, (Object) a);
_
Object
にキャストすると、varargメカニズムが配列を作成する作業を実行します。
このトリックは、引数としてnull
をvarargsに渡すときにも必要であり、リフレクションとは関係ありません。
_public void foo(String... ss) {
System.out.println(ss[0]);
}
foo(null); // causes NullPointerException
foo((String) null); // prints "null"
_