リフレクションAPIとJavaBeans

 リフレクションAPI(java.lang.reflectパッケージ) を使うと、 Javaアプリケーションの実行中に、 Javaクラスのメソッドやフィールド(メンバ変数)などの仕様を取得することができます。 またコンパイル時に正確なクラスが判明していないオブジェクトを、 特定のクラスのインスタンスとして実行時に作成・利用することができます。 一見、何に使うの?というリフレクションAPIですが、 JavaBeansクラスのプロパティにアクセスするような汎用ツールを作る際にとても便利に使えます。 Beansクラスはクラスによって異なるプロパティ値を持ち、 それに対応する名前のset/getメソッド (例えば、プロパティがmessageならsetMessage()&getMessage()メソッド) を持つのですが、さまざまなBeansに対応するツールを作ろうとすると、 それらのプロパティ名/メソッド名をソースプログラムに直接書くことができません。 そこで、それらは実行時のパラメータや設定などから動的に取得する必要が生じますが、 その際に使うのがリフレクションAPI、というわけです。

 下の例はあまり意味はないサンプルです。 コンストラクタの引数で指定した名前のクラスのオブジェクトを生成し、 その(これまたコンストラクタの引数で指定した)プロパティに値をセットし、 すぐにそれを取得し、標準出力に印字して終了します。

import java.lang.reflect.*;

public class ReflectionExample {
  private Class c;
  private Object obj;

  public ReflectionExample(String className, String propName, String propValue)
  throws ClassNotFoundException, InstantiationException,
         NoSuchMethodException, IllegalAccessException,
         InvocationTargetException {
    c = Class.forName(className);
    obj = c.newInstance();
    setProperty(propName, propValue);
    String s = getProperty(propName);
  }

  private void setProperty(String name, String value)
  throws ClassNotFoundException, NoSuchMethodException,
         IllegalAccessException, InvocationTargetException {
    String methodName = "set" + name.substring(0, 1).toUpperCase() +
      name.substring(1);
    Class[] paramTypes = {Class.forName("java.lang.String")};
    String[] values = {value};
    Method m = c.getMethod(methodName, paramTypes);
    m.invoke(obj, values);
    System.out.println("プロパティ " + name + " に " + value +
 " をセットしました。");
  }

  private String getProperty(String name)
  throws NoSuchMethodException,
         IllegalAccessException, InvocationTargetException {
    String methodName = "get" + name.substring(0, 1).toUpperCase() +
      name.substring(1);
    Class[] paramTypes = null;
    Method m = c.getMethod(methodName, paramTypes);
    String s = (String) m.invoke(obj, null);
    System.out.println("プロパティ " + name + " の値は " + s + " です。");
    return s;
  }

  public static void main(String[] args) throws Exception {
    ReflectionExample my =
      new ReflectionExample("my.sample.HelloWorld", "message", "Hello");
  }
}
/* end.*/

 文字列で指定したクラスのインスタンスを作るには、 まずClass.forNameメソッドでクラスのオブジェクトを取得し、 そのnewInstanceメソッドを使います。 この例では、引数のないコンストラクタを持つ(Beansの必須条件のひとつです) クラスということで、簡単に作れていますが、 引数を持つコンストラクタをコールしてインスタンスを作ることもできます。

 メソッドをコールするには、 まずクラスオブジェクトのgetMethodメソッドを使い、 メソッドオブジェクト(Methodのインスタンス)を取得します。 その引数にメソッド名と引数のデータ型をクラスオブジェクトの配列で指定したものを渡して、 メソッドを特定します。 メソッドオブジェクトが取得できたら、そのinvokeメソッドで、 メソッドをコールすることができます。 メソッドへの引数は配列でinvoke()に渡します。 invoke()の戻り値は、コールしたメソッドの戻り値がjava.lang.Object として返って来るので、適当にキャストする必要があります。

 なおこのサンプルでは、プロパティ名からメソッド名を作る際に、 プロパティ名の先頭を大文字(message→Message)にして、 set/getをつける(setMessage/getMessage)という処理にしています。

Java kowaza Top

(first uploaded 2003/02/17 last updated (not ever), URANO398)

テレワークならECナビ Yahoo 楽天 LINEがデータ消費ゼロで月額500円〜!
無料ホームページ 無料のクレジットカード 海外格安航空券 海外旅行保険が無料! 海外ホテル