リフレクションを試す

戻る
java.lanag.reflectパッケージの使用例です。 外部に記述した定義ファイル(XMLなど)でクラスの振る舞いを動的に操作する場合などに使えます。 injection(注入)というか、intervention(介入)というか、そんなことが可能になるわけです。 例えば、事前に生成されたインスタンスの状態に応じた 処理フローを、ハードコーディングしないで外部から制御できるなんていうのもOne of themです。 クラス名、メソッド名およびメソッドが返す値を外部から参照して、更新できるということが味噌ってことです。
::::::::::::::
result.txt
::::::::::::::
$ java ReflectionTest3

クラス名: Sample	

	メソッド名: setGender	戻り値の型: void
	(第 1 引数の型) Gender$Type

	メソッド名: setAge	戻り値の型: void
	(第 1 引数の型) int

	メソッド名: getAge	戻り値の型: int

	メソッド名: getGender	戻り値の型: Gender$Type

	メソッド名: getName	戻り値の型: java.lang.String

	メソッド名: setName	戻り値の型: void
	(第 1 引数の型) java.lang.String

	メソッド名: hashCode	戻り値の型: int

	メソッド名: getClass	戻り値の型: java.lang.Class

	メソッド名: wait	戻り値の型: void

	メソッド名: wait	戻り値の型: void
	(第 1 引数の型) long
	(第 2 引数の型) int

	メソッド名: wait	戻り値の型: void
	(第 1 引数の型) long

	メソッド名: equals	戻り値の型: boolean
	(第 1 引数の型) java.lang.Object

	メソッド名: notify	戻り値の型: void

	メソッド名: notifyAll	戻り値の型: void

	メソッド名: toString	戻り値の型: java.lang.String

// クラス名: Sample	メソッド名: getName
戻り値=岸 康弘

::::::::::::::
ReflectionTest3.java
::::::::::::::
import java.lang.reflect.*;

/**
$Id: reflect.html,v 1.1 2009/06/22 16:12:22 kishi Exp kishi $
*/

public class ReflectionTest3 {

    static public void main( String[] args ) throws Exception {

        // クラスを取得
        Class clazz;
        try {
            clazz = Class.forName( "Sample" );
        } catch ( ClassNotFoundException e ) {
            e.printStackTrace();
            throw e;
        }

        // インスタンスを生成
        Object instance;
        try {
            instance = clazz.newInstance();
        } catch ( InstantiationException e ) {
            e.printStackTrace();
            throw e;
        } catch ( IllegalAccessException e ) {
            e.printStackTrace();
            throw e;
        }

        /** このクラスが保有するメソッドの名前、戻り値の型、引数の型をダンプする*/
        dumpMethodInfo( clazz );

        /** Setter系のメソッドを実行する */
        invokeSetterMethod( instance, "setName", new Object[] {"岸 康弘"} ); // 引数をObject型の配列で渡す

        /** Getter系のメソッドを実行する */
        Object ret = invokeGetterMethod( instance, "getName", null ); // 引数をObject型の配列で渡す
        System.out.println( "戻り値=" + ret );

    }

    /** Setter系のメソッドを実行する */
    static public void invokeSetterMethod( Object instance, String methodName, Object[] argv ) throws Exception {

        Method method = getMethod( instance, methodName );

        // メソッド実行
        try {
            method.invoke( instance, argv );
        } catch ( IllegalArgumentException e ) {
            e.printStackTrace();
            throw e ;
        } catch ( IllegalAccessException e ) {
            e.printStackTrace();
            throw e ;
        } catch ( InvocationTargetException e ) {
            e.getCause().printStackTrace();
            throw e ;
        }

    }

    /** Getter系のメソッドを実行する */
    static public Object invokeGetterMethod( Object instance, String methodName, Object[] argv ) throws Exception {

        Method method = getMethod( instance, methodName );

        //========================================================================================
        // メソッド実行 -- invokeStterMethod()との違いは、戻り値があるかないかの違いだけ
        //========================================================================================
        Object ret = null;
        try {
            ret = method.invoke( instance, argv );
        } catch ( Exception e ) {
            e.printStackTrace();
        }

        System.out.print( "// クラス名: " + instance.getClass().getName() );
        System.out.print( "\tメソッド名: " + methodName );
        System.out.println();

        return ret;

    }

    static private Method getMethod( Object instance, String methodName ) throws Exception {
        Class clazz = instance.getClass();

        // 引数の型を求める
        Class[] types = getArgTypes( clazz, methodName );

        Method method = null;
        try {
            //-------------- ハードコーディングする場合はこんな感じです --------------------------------------
            // method = instance.getClass().getMethod( methodName, new Class[] {String.class} );
            //------------------------------------------------------------------------------------------------
            method = clazz.getMethod( methodName, types );
        } catch ( Exception e ) {
            e.printStackTrace();
            throw e;
        }
        return method;
    }

    /** このクラスが保有するメソッドの名前、戻り値の型、引数の型をダンプする*/
    static public void dumpMethodInfo( Class clazz ) {
        System.out.print( "クラス名: " + clazz.getName() );

        Class[] types = null;
        Method[] methods = clazz.getMethods();
        for ( int i = 0;i < methods.length;i++ ) {
            System.out.print( "\tメソッド名: " + methods[ i ].getName() );
            System.out.print( "\t戻り値の型: " + methods[ i ].getReturnType().getName() );
            System.out.println();

            //引数の型を取得
            Class[] params = methods[ i ].getParameterTypes();
            for ( int j = 0;j < params.length;j++ ) {
                System.out.printf( "\t(第%2d 引数の型) %s\n" , j + 1, params[ j ].getName() );
            }

            System.out.println();
        }
    }

    /** 引数の型を求める */
    static private Class[] getArgTypes( Class clazz, String methodName ) {

        Class[] types = null;
        Method[] methods = clazz.getMethods();
        for ( int i = 0;i < methods.length;i++ ) {

            //引数の型を取得
            Class[] params = methods[ i ].getParameterTypes();

            // メソッド名が指定したものと一致した場合は引数のタイプを取得する
            if ( methods[ i ].getName().equals( methodName ) ) {
                types = params;
            }
        }
        return types;
    }
}
::::::::::::::
Sample.java
::::::::::::::
/**
$Id: reflect.html,v 1.1 2009/06/22 16:12:22 kishi Exp kishi $
*/

public class Sample {
    private String name;
    private int age;
    private Gender.Type gender;

    public void setGender( Gender.Type gender ) {
        this.gender = gender;
    }

    public void setName( String name ) {
        this.name = name;
    }

    public void setAge( int age ) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }
    public String getName() {
        return name;
    }

    public Gender.Type getGender() {
        return gender;
    }
}
::::::::::::::
Gender.java
::::::::::::::
/**
$Id: reflect.html,v 1.1 2009/06/22 16:12:22 kishi Exp kishi $
*/

public class Gender {
    static public enum Type {MALE, FEMALE, UNKNOWN}

}
戻る inserted by FC2 system