Method.invoke - Javaメソッドの動的に実行
2009/02/13 11:59Update
Javaリフレクション機能を利用して、Javaメソッドを動的に実行させるサンプルです。
Javaでは、クラスとオブジェクトに関するリフレクト情報を取得するAPIを提供します。
これらのリフレクションAPIはjava.lang.reflectパッケージにまとめて提供されています。
◇ 設定ファイルから指定するクラスやメソッドを実行する必要がある場合。たとえば、HibernateなどのORMツールは、設定ファイルに書かれたJDBCドライバークラスを変えるだけで、違うデータベースに接続させる仕組みはリフレクションを利用しています。
◇ フレームワークや外部ツールなど。SpringやJSF、Strutsなどのフレームワークは、動的にインスタンスの生成やメソッドの呼び出しがあります。これらのフレームワークもJavaリフレクション機能を利用しています。
動的にクラスに実行について、次の記事をご参照ください。
Class.forName/newInstance - 文字列からインスタンスを生成
本文は、Javaメソッドを動的に実行させる方法および実装手順について学びます。
関連するリフレクト情報を取得するクラスおよびインタフェース
java.lang.reflect.Method
java.lang.reflect.Field
シンプルなサンプルから説明します。
Javaコード:
実行結果:
簡単に説明します。
上のサンプルは、オブジェクトに対して、文字列で指定するフィールドの値を動的に取得/セットする例です。
1)オブジェクトのClass情報を取得
MyClass.classやobject.getClass()などで取得します。
2)フィールドの値を取得/セットするためのメソッド名を取得
例えば、MyClassの"userName"というフィールドの値の取得するメソッド名はgetUserNameです。
3)Class情報から指定するメソッド名のMethod情報を取得
例:
Method method = cls.getMethod(setterMethod, argTypes);
4)Method.invokeでメソッドを実行して、フィールドの値を取得/セットします。
例:
method.invoke(object, argValues);
これらのリフレクションAPIはjava.lang.reflectパッケージにまとめて提供されています。
Javaリフレクションの使用シーン
◇ 設定ファイルから指定するクラスやメソッドを実行する必要がある場合。たとえば、HibernateなどのORMツールは、設定ファイルに書かれたJDBCドライバークラスを変えるだけで、違うデータベースに接続させる仕組みはリフレクションを利用しています。
◇ フレームワークや外部ツールなど。SpringやJSF、Strutsなどのフレームワークは、動的にインスタンスの生成やメソッドの呼び出しがあります。これらのフレームワークもJavaリフレクション機能を利用しています。
動的にクラスに実行について、次の記事をご参照ください。
Class.forName/newInstance - 文字列からインスタンスを生成
本文は、Javaメソッドを動的に実行させる方法および実装手順について学びます。
関連するリフレクト情報を取得するクラスおよびインタフェース
java.lang.reflect.Method
java.lang.reflect.Field
サンプル
シンプルなサンプルから説明します。
Javaコード:
package com.test.reflection;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* リフレクション・サンプル
* 1)指定するフィールド名のフィールド値を取得
* 2)指定するフィールド名のフィールド値を設定
* 3)動的にMethodを実行(Method.invoke)
*
*/
public class TestReflection {
public static void main(String []args) {
try {
MyClass obj = new MyClass("Hello", 20);
System.out.println("****************フィールド値取得*****************");
String userName = (String)getFieldValueByName(obj, "userName");
int age = (Integer)getFieldValueByName(obj, "age");
System.out.println(userName);
System.out.println(age);
System.out.println("****************フィールド値設定*****************");
setFieldValueByName(obj, "userName", "新しい名だよ");
setFieldValueByName(obj, "age", 30);
System.out.println(obj.getUserName());
System.out.println(obj.getAge());
} catch (Exception e) { //by Class.forName
e.printStackTrace();
}
}
/**
* オブジェクトのフィールド値を取得する
* @param object 取得する対象となるオブジェクト
* @param fieldName フィールド名
*
*/
public static Object getFieldValueByName(
Object object, String fieldName)
throws SecurityException, NoSuchMethodException,
IllegalArgumentException, IllegalAccessException, InvocationTargetException {
if (object == null)
return null;
Class cls = object.getClass();
//フィールドのgetメソッド名を取得
char firstChar = fieldName.charAt(0);
char uFirstChar = Character.toUpperCase(firstChar);
String getMethod = "get"
+ fieldName.replaceFirst(String.valueOf(firstChar),
String.valueOf(uFirstChar));
//getメソッドを取得
Method method = cls.getMethod(getMethod, null);
//getメソッドを呼び出し、戻り値はフィールドの値になります
Object objValue = method.invoke(object, null);
return objValue;
}
/**
* オブジェクトのフィールド値を設定する
* @param object 対象となるオブジェクト
* @param fieldName フィールド名
*
*/
public static void setFieldValueByName(
Object object,
String fieldName,
Object fieldValue)
throws SecurityException, NoSuchFieldException, IllegalArgumentException,
IllegalAccessException, InvocationTargetException, NoSuchMethodException {
if (object == null) {
return;
}
Class cls = object.getClass(); //オブジェクトのClass取得
Field field = cls.getDeclaredField(fieldName); //文字列(フィールド名)からFieldオブジェクト取得
Class fieldType = field.getType(); //フィールドの型取得
Class [] argTypes = {fieldType};
Object[] argValues = {fieldValue};
setFieldValueByName(cls, object, fieldName, argTypes, argValues);
}
public static void setFieldValueByName(Class cls,
Object object,
String fieldName,
Class [] argTypes,
Object [] argValues)
throws SecurityException, NoSuchFieldException, IllegalArgumentException,
IllegalAccessException, InvocationTargetException, NoSuchMethodException {
if (object == null)
return;
//setメソッド名
char firstChar = fieldName.charAt(0);
char uFirstChar = Character.toUpperCase(firstChar);
String setterMethod = "set"
+ fieldName.replaceFirst(String.valueOf(firstChar),
String.valueOf(uFirstChar));
//setメソッド
Method method = cls.getMethod(setterMethod, argTypes);
//setメソッド実行(オブジェクト、パラメータ)
method.invoke(object, argValues);
}
}
class MyClass {
private String userName;
private int age;
public MyClass(String userName, int age) {
this.userName = userName;
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
実行結果:
****************フィールド値取得*****************
Hello
20
****************フィールド値設定*****************
新しい名だよ
30
Hello
20
****************フィールド値設定*****************
新しい名だよ
30
簡単に説明します。
上のサンプルは、オブジェクトに対して、文字列で指定するフィールドの値を動的に取得/セットする例です。
1)オブジェクトのClass情報を取得
MyClass.classやobject.getClass()などで取得します。
2)フィールドの値を取得/セットするためのメソッド名を取得
例えば、MyClassの"userName"というフィールドの値の取得するメソッド名はgetUserNameです。
3)Class情報から指定するメソッド名のMethod情報を取得
例:
Method method = cls.getMethod(setterMethod, argTypes);
4)Method.invokeでメソッドを実行して、フィールドの値を取得/セットします。
例:
method.invoke(object, argValues);
Sponsored Link
Comments
- Relative Articles
- Java Generics使い方 - Genericsメソッドを定義してみる - (2009/02/20 16:02)
- Java オブジェクトのclone 概要 - (2009/06/02 17:18)
- Java クラス概要 - (2008/10/04 00:42)
- Javaクラスのコンストラクタメソッドの定義方法 - (2009/09/30 16:56)
- Collections.sortでList要素をソートさせる - (2009/01/30 14:31)
- System.currentTimeMillis - 現在時刻を数値で取得 - (2009/02/10 11:59)
- JavaでString文字列が等しいかどうかの判定 - (2009/02/23 13:41)
- String.splitで正規表現によるString文字列の分割 - (2009/03/04 14:24)
- Java Math.randomやRandom による乱数の生成 - (2010/04/21 15:10)
- List.toArray()/toArray(T []arg0) - Listから配列への変換例 - (2010/06/09 18:25)