トッカンソフトウェア

リフレクション

リフレクションをやってみます。リフレクションを使うとクラス名、メソッド名からメソッドを呼び出すことができます。



クラス名、メソッド名を指定

リフレクションを使って、クラス名、メソッド名からメソッドを実行します。スタティックメソッドはそのまま呼び出せますが、通常のメソッドはオブジェクトを生成してからメソッドを呼び出します。

Test.java

package javaTest;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class Test {

	public static void main(String[] args) {
		Test t = new Test();

		// リフレクションでスタティックメソッドを実行
		System.out.println(t.execStatic("javaTest.Test", "execStatic1"));

		// リフレクションでスタティックメソッドを実行(引数あり)
		System.out.println(t.execStatic("javaTest.Test", "execStatic2", "abc", "def"));

		// リフレクションでメソッドを実行
		System.out.println(t.exec("javaTest.Test", "exec1"));

		// リフレクションでメソッドを実行(引数あり)
		System.out.println(t.exec("javaTest.Test", "exec2", "aaa", "aaa"));
	}

	/**
	 * リフレクションでスタティックメソッドを実行
	 * 
	 * @param className  クラス名
	 * @param methodName メソッド名
	 * @return 戻り値
	 */
	public Object execStatic(String className, String methodName) {
		Object ret = null;
		try {
			Class<?> clazz = Class.forName(className);
			Method method = clazz.getMethod(methodName);
			ret = method.invoke(null);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return ret;
	}

	/**
	 * リフレクションでスタティックメソッドを実行(引数あり)
	 * 
	 * @param className  クラス名
	 * @param methodName メソッド名
	 * @param arg1       引数1
	 * @param arg2       引数2
	 * @return 戻り値
	 */
	public Object execStatic(String className, String methodName, String arg1, String arg2) {
		Object ret = null;
		try {
			Class<?> clazz = Class.forName(className);
			Method method = clazz.getMethod(methodName, arg1.getClass(), arg2.getClass());
			ret = method.invoke(null, arg1, arg2);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return ret;
	}

	/**
	 * リフレクションでメソッドを実行
	 * 
	 * @param className  クラス名
	 * @param methodName メソッド名
	 * @return 戻り値
	 */
	public Object exec(String className, String methodName) {
		Object ret = null;
		try {
			Class<?> clazz = Class.forName(className);
			Method method = clazz.getMethod(methodName);
			ret = method.invoke(getInstance(clazz));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return ret;
	}

	/**
	 * リフレクションでメソッドを実行(引数あり)
	 * 
	 * @param className  クラス名
	 * @param methodName メソッド名
	 * @param arg1       引数1
	 * @param arg2       引数2
	 * @return 戻り値
	 */
	public Object exec(String className, String methodName, String arg1, String arg2) {
		Object ret = null;
		try {
			Class<?> clazz = Class.forName(className);
			Method method = clazz.getMethod(methodName, String.class, String.class);
			ret = method.invoke(getInstance(clazz), arg1, arg2);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return ret;
	}

	/**
	 * オブジェクトを生成
	 * 
	 * @param clazz クラス
	 * @return オブジェクト
	 * @throws Exception 実行時例外
	 */
	public Object getInstance(Class<?> clazz) throws Exception {
		Object ret = null;

		Constructor<?> constructor = clazz.getConstructor();

		ret = constructor.newInstance();

		return ret;
	}

	public static void execStatic1() {
		System.out.println("doStatic1");
	}

	public static String execStatic2(String arg1, String arg2) {
		System.out.println("doStatic2");
		return arg1 + arg2;
	}

	public void exec1() {
		System.out.println("exec1");
	}

	public boolean exec2(String arg1, String arg2) {
		System.out.println("exec2");
		return arg1.equals(arg2);
	}

}
実行結果
				
doStatic1
null
doStatic2
abcdef
exec1
null
exec2
true

			

クラス名のみ指定

クラス名からリフレクションを使って、オブジェクトを生成し、対象クラスにキャストして、メソッドを呼び出してみます。

Test.java
				
package javaTest;

import java.lang.reflect.Constructor;

public class Test {

	public static void main(String[] args) {
		Test t = new Test();

		// リフレクションでメソッドを実行
		System.out.println(t.exec("javaTest.TestImpl", "aaa", "bbb"));
	}

	/**
	 * リフレクションでメソッドを実行(引数あり)
	 * 
	 * @param className クラス名
	 * @param arg1      引数1
	 * @param arg2      引数2
	 * @return 戻り値
	 */
	public String exec(String className, String arg1, String arg2) {
		try {
			IfTest obj = (IfTest) getInstance(className);
			return obj.execute(arg1, arg2);
		} catch (Exception e) {

			e.printStackTrace();
		}
		return null;
	}

	/**
	 * オブジェクトを生成
	 * 
	 * @param className クラス名
	 * @return オブジェクト
	 * @throws Exception 実行時例外
	 */
	public Object getInstance(String className) throws Exception {
		Object ret = null;
		Class<?> clazz = Class.forName(className);

		Constructor<?> constructor = clazz.getConstructor();

		ret = constructor.newInstance();

		return ret;
	}

}


			
IfTest.java
				
package javaTest;

public interface IfTest {

	public String execute(String arg1, String arg2);
}

			
TestImpl.java
				
package javaTest;

public class TestImpl implements IfTest {

	@Override
	public String execute(String arg1, String arg2) {
		return arg1 + arg2;
	}
}

			
実行結果
				
aaabbb

			



キャストしなくてもクラス指定でオブジェクト作成することもできます。

package javaTest;

import java.lang.reflect.Constructor;

public class Test {

	public static void main(String[] args) {
		Test t = new Test();

		// リフレクションでメソッドを実行
		System.out.println(t.exec("javaTest.TestImpl", "aaa", "bbb"));
	}

	/**
	 * リフレクションでメソッドを実行(引数あり)
	 * 
	 * @param className クラス名
	 * @param arg1      引数1
	 * @param arg2      引数2
	 * @return 戻り値
	 */
	public String exec(String className, String arg1, String arg2) {
		try {
			IfTest obj = getInstance(className);
			return obj.execute(arg1, arg2);
		} catch (Exception e) {

			e.printStackTrace();
		}
		return null;
	}

	/**
	 * オブジェクトを生成
	 * 
	 * @param className クラス名
	 * @return オブジェクト
	 * @throws Exception 実行時例外
	 */
	public IfTest getInstance(String className) throws Exception {
		IfTest ret = null;
		Class<? extends IfTest> clazz = Class.forName(className).asSubclass(IfTest.class);

		Constructor<? extends IfTest> constructor = clazz.getConstructor();

		ret = constructor.newInstance();

		return ret;
	}

}



ページのトップへ戻る