■
先日のClassクラスのnewInstance()は動的なインスタンス生成を実現したわけだけども、どうせなら動的に生成したインスタンスのメソッドを動的にinvokeしたい。
それを実現するのがjava.lang.reflect.Methodクラス。
ではここで、以下のようなa1メソッドを様々な引数でオーバーロードしたTestクラスを考える。
package a; public class Test { public void a1(){ System.out.println("I'm method a1()"); } public void a1(int a){ System.out.println("I'm method a1(int a))"); System.out.println("a = " + a); } public void a1(int a, Object b){ System.out.println("I'm method a1(int a, Object b"); System.out.println("a = " + a); System.out.println("b.toString() = " + b); } }
でこれらのメソッドを動的にinvokeするには・・・
package a; public class Main { public static void main(String[] args){ Class classInstance = Class.forName("a.Test"); // Method m1 = classInstance.getMethod("a1", new Class[0]); //(1) Method m1 = classInstance.getMethod("a1"); //(2) m1.invoke(classInstance.newInstance(), new Object[0]); //(3) Class[] c1 = new Class[1]; c1[0] = Integer.TYPE; Method m2 = classInstance.getMethod("a1", c1); //(4) m2.invoke(classInstance.newInstance(), new Integer(1)); //(5) Method m3 = classInstance.getMethod ("a1", Integer.TYPE, new Object().getClass()); //(6) m3.invoke (classInstance.newInstance(), new Integer(2), new Object()); //(7) } }
ここで、コメントアウトしてる(1) or (2)の部分はインスタンスから、引数がないメソッドa1を取得してる。引数が無いことを示すためには(1)のように空配列(empty array)指定することでも示せるし、(2)の部分のように何も書かないって事でも示すことができる。
また引数がある場合、クラスの種類を格納したClassクラスの配列を作り、それを(4)のようにgetMethodの第2引数にすることでメソッドを指定してもいいし、ただ型を示すClassクラスを並べるってだけでもいい。
このことは、メソッドをinvokeする場合も同じで((3),(5),(7))、引数を指定するのにObjectクラスの配列を利用してもいいし、そのまま(7)のように並べてもいい。
(注意)例外処理、importは簡単化のためソースから省いてるよ。
〜補足〜
ここで、Integerクラスのstaticフィールド、TYPEは、int のプリミティブ型を表すClassインスタンス。
(7)では、int型の引数のところにラッパクラスであるIntegerを入れてるが、これは実際にinvokeする際、VMが自動的にアンラップしてくれる。