FC2ブログ
HOME   »  2013年01月
Archive | 2013年01月

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

[Java]リフレクションを使用したクラスメンバー情報の取得

リフレクションを使用したクラスメンバー情報の取得について。

Classクラスで定義されているメソッドを使用して、任意のクラスのメンバー(フィールド、コンストラクタ、メソッド)の情報を取得することができる。

以下の様なクラス(Superクラスとそれを継承したSubクラス)がある。

○Superクラス
package reflectiontest.superpackage;

public class Super {
    int defaultSuperField;
    private int privateSuperField;
    protected int protectedSuperField;
    public int publicSuperField;

    //サブクラスからの暗黙的呼び出し用コンストラクタ
    protected Super() {
    }

    Super(int defaultValue) {
        defaultSuperField = defaultValue;
    }

    private Super(int defaultValue, int privateValue) {
        defaultSuperField = defaultValue;
        privateSuperField = privateValue;
    }

    protected Super(int defaultValue, int privateValue, int protectedValue) {
        defaultSuperField = defaultValue;
        privateSuperField = privateValue;
        protectedSuperField = protectedValue;
    }

    public Super(int defaultValue, int privateValue, int protectedValue, int publicValue) {
        defaultSuperField = defaultValue;
        privateSuperField = privateValue;
        protectedSuperField = protectedValue;
        publicSuperField = publicValue;
    }

    void defaultSuperMethod() {
        System.out.println("defaultSuperMethodが実行されました。");
    }

    private void privateSuperMethod() {
        System.out.println("privateSuperMethodが実行されました。");
    }

    protected void protectedSuperMethod() {
        System.out.println("protectedSuperMethodが実行されました。");
    }

    public void publicSuperMethod() {
        System.out.println("publicSuperMethodが実行されました。");
    }
}
○Subクラス
package reflectiontest.subpackage;

public class Sub extends reflectiontest.superpackage.Super {
    int defaultSubField;
    private int privateSubField;
    protected int protectedSubField;
    public int publicSubField;

    Sub(int defaultValue) {
        defaultSubField = defaultValue;
    }

    private Sub(int defaultValue, int privateValue) {
        defaultSubField = defaultValue;
        privateSubField = privateValue;
    }

    protected Sub(int defaultValue, int privateValue, int protectedValue) {
        defaultSubField = defaultValue;
        privateSubField = privateValue;
        protectedSubField = protectedValue;
    }

    public Sub(int defaultValue, int privateValue, int protectedValue, int publicValue) {
        defaultSubField = defaultValue;
        privateSubField = privateValue;
        protectedSubField = protectedValue;
        publicSubField = publicValue;
    }

    void defaultSubMethod() {
        System.out.println("defaultSubMethodが実行されました。");
    }

    private void privateSubMethod() {
        System.out.println("privateSubMethodが実行されました。");
    }

    protected void protectedSubMethod() {
        System.out.println("protectedSubMethodが実行されました。");
    }

    public void publicSubMethod() {
        System.out.println("publicSubMethodが実行されました。");
    }
}
そして、以下の様にリフレクションを使用して上記のSuperクラス、Subクラスのメンバー情報を取得する。
public class Main {
    public static void main(String[] args) {
        Class<?> clazz;
        Field[] fields;
        Constructor<?>[] constructors;
        Method[] methods;
        try {
            clazz = Class.forName("reflectiontest.superpackage.Super");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            return;
        }
        fields = clazz.getFields();
        System.out.println("getFields()メソッドで取得したSuperクラスのフィールド");
        for (Field field : fields) {
            System.out.println(field.getName());
        }
        fields = clazz.getDeclaredFields();
        System.out.println("");
        System.out.println("getDeclaredFields()メソッドで取得したSuperクラスのフィールド");
        for (Field field : fields) {
            System.out.println(field.getName());
        }
        constructors = clazz.getConstructors();
        System.out.println("");
        System.out.println("getConstructors()メソッドで取得したSuperクラスのコンストラクタ");
        for (Constructor<?> constructor : constructors) {
            System.out.println(constructor.getName());
        }
        constructors = clazz.getDeclaredConstructors();
        System.out.println("");
        System.out.println("getDeclaredConstructors()メソッドで取得したSuperクラスのコンストラクタ");
        for (Constructor<?> constructor : constructors) {
            System.out.println(constructor.getName());
        }
        methods = clazz.getMethods();
        System.out.println("");
        System.out.println("getMethods()メソッドで取得したSuperクラスのメソッド");
        for (Method method : methods) {
            System.out.println(method.getName());
        }
        methods = clazz.getDeclaredMethods();
        System.out.println("");
        System.out.println("getDeclaredMethods()メソッドで取得したSuperクラスのメソッド");
        for (Method method : methods) {
            System.out.println(method.getName());
        }
        try {
            clazz = Class.forName("reflectiontest.subpackage.Sub");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            return;
        }
        fields = clazz.getFields();
        System.out.println("");
        System.out.println("getFields()メソッドで取得したSubクラスのフィールド");
        for (Field field : fields) {
            System.out.println(field.getName());
        }
        fields = clazz.getDeclaredFields();
        System.out.println("");
        System.out.println("getDeclaredFields()メソッドで取得したSubクラスのフィールド");
        for (Field field : fields) {
            System.out.println(field.getName());
        }
        constructors = clazz.getConstructors();
        System.out.println("");
        System.out.println("getConstructors()メソッドで取得したSubクラスのコンストラクタ");
        for (Constructor<?> constructor : constructors) {
            System.out.println(constructor.getName());
        }
        constructors = clazz.getDeclaredConstructors();
        System.out.println("");
        System.out.println("getDeclaredConstructors()メソッドで取得したSubクラスのコンストラクタ");
        for (Constructor<?> constructor : constructors) {
            System.out.println(constructor.getName());
        }
        methods = clazz.getMethods();
        System.out.println("");
        System.out.println("getMethods()メソッドで取得したSubクラスのメソッド");
        for (Method method : methods) {
            System.out.println(method.getName());
        }
        methods = clazz.getDeclaredMethods();
        System.out.println("");
        System.out.println("getDeclaredMethods()メソッドで取得したSubクラスのメソッド");
        for (Method method : methods) {
            System.out.println(method.getName());
        }
    }
}
8行目でSuperクラスについてのClassクラスのインスタンスを取得して、13行目と18行目でフィールド情報(Superクラスの各フィールドについてのFieldクラスインスタンス)、24行目と30行目でコンストラクタ情報(Superクラスの各コンストラクタについてのConstructorクラスインスタンス)、36行目と42行目でメソッド情報(Superクラスの各メソッドについてのMethodクラスインスタンス)を取得している。

引き続いて、49行目でSubクラスについてのClassクラスのインスタンスを取得して、54行目と60行目でフィールド情報(Subクラスの各フィールドについてのFieldクラスインスタンス)、66行目と72行目でコンストラクタ情報(Subクラスの各コンストラクタについてのConstructorクラスインスタンス)、78行目と84行目でメソッド情報(Subクラスの各メソッドについてのMethodクラスインスタンス)を取得している。

ClassクラスのgetFieldsメソッド、getMethodsメソッドは、それぞれ対象クラスとそのスーパークラスで定義されているpublicフィールド、publicメソッドの情報を取得することができる。
getDeclaredFieldsメソッド、getDeclaredMethodsメソッドは、それぞれ対象クラスで定義されている全フィールド、全メソッドの情報を取得することができる。
getConstructorsメソッドは対象クラスで定義されているpublicコンストラクタ、getDeclaredConstructorsメソッドは対象クラスで定義されている全コンストラクタの情報を取得することができる。

上記の実行結果をメソッド毎に見ていく。

○getFieldsメソッド

getFields()メソッドで取得したSuperクラスのフィールド
publicSuperField

Superクラスで定義されているpublicフィールドの情報が取得できている。
スーパークラスであるObjectクラスにはpublicフィールドがない為、情報はない。


getFields()メソッドで取得したSubクラスのフィールド
publicSubField
publicSuperField

SubクラスとそのスーパークラスであるSuperクラスで定義されているpublicフィールドの情報が取得できている。
Superクラスと同様に、Objectクラスの情報はない。

○getDeclaredFieldsメソッド

getDeclaredFields()メソッドで取得したSuperクラスのフィールド
defaultSuperField
privateSuperField
protectedSuperField
publicSuperField

Superクラスで定義されている全フィールドの情報が取得できている。


getDeclaredFields()メソッドで取得したSubクラスのフィールド
defaultSubField
privateSubField
protectedSubField
publicSubField

Subクラスで定義されている全フィールドの情報が取得できている。

○getConstructorsメソッド

getConstructors()メソッドで取得したSuperクラスのコンストラクタ
reflectiontest.superpackage.Super

Superクラスで定義されているpublicコンストラクタの情報が取得できている。


getConstructors()メソッドで取得したSubクラスのコンストラクタ
reflectiontest.subpackage.Sub

Subクラスで定義されているpublicコンストラクタの情報が取得できている。

○getDeclaredConstructorsメソッド

getDeclaredConstructors()メソッドで取得したSuperクラスのコンストラクタ
reflectiontest.superpackage.Super
reflectiontest.superpackage.Super
reflectiontest.superpackage.Super
reflectiontest.superpackage.Super
reflectiontest.superpackage.Super

Superクラスで定義されている全コンストラクタ(シグネチャ違いの5つ)の情報が取得できている。


getDeclaredConstructors()メソッドで取得したSubクラスのコンストラクタ
reflectiontest.subpackage.Sub
reflectiontest.subpackage.Sub
reflectiontest.subpackage.Sub
reflectiontest.subpackage.Sub

Subクラスで定義されている全コンストラクタ(シグネチャ違いの4つ)の情報が取得できている。

○getMethodsメソッド

getMethods()メソッドで取得したSuperクラスのメソッド
publicSuperMethod
wait
wait
wait
equals
toString
hashCode
getClass
notify
notifyAll

SuperクラスとそのスーパークラスであるObjectクラスで定義されているpublicメソッドの情報が取得できている。


getMethods()メソッドで取得したSubクラスのメソッド
publicSubMethod
publicSuperMethod
wait
wait
wait
equals
toString
hashCode
getClass
notify
notifyAll

SubクラスとそのスーパークラスであるSuperクラス、Objectクラスで定義されているpublicメソッドの情報が取得できている。

○getDeclaredMethodsメソッド

getDeclaredMethods()メソッドで取得したSuperクラスのメソッド
defaultSuperMethod
privateSuperMethod
protectedSuperMethod
publicSuperMethod

Superクラスで定義されている全メソッドの情報が取得できている。


getDeclaredMethods()メソッドで取得したSubクラスのメソッド
defaultSubMethod
privateSubMethod
protectedSubMethod
publicSubMethod

Subクラスで定義されている全メソッドの情報が取得できている。


スポンサーサイト

[Android]Buttonを押さずにonClickイベントを発生させる

Buttonを押さずにonClickイベントを発生させる方法。

Button(View)のsetOnClickListenerメソッドでOnClickListener(インタフェースを実装したクラスのインスタンス)を設定しておくと、Buttonが押された際にOnClickListenerのonClickメソッドが呼び出される。
通常は物理的にButtonを押す(クリックする)ことによりこのonClickメソッドが呼び出されるが、Buttonを押す代わりにButton(View)のperformClickメソッドを実行することでもonClickメソッドを呼び出すことができる。

ViewクラスのソースコードでperformClickメソッドを見ると、
public boolean performClick() {
    sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);

    if (mOnClickListener != null) {
        playSoundEffect(SoundEffectConstants.CLICK);
        mOnClickListener.onClick(this);
        return true;
    }

    return false;
}
となっており、mOnClickListener(setOnClickListenerメソッドで設定したOnClickListener)のonClickメソッドが実行されている。

以下の例で確認してみる。

まず、下記の様なButton 2個とTextView 1個のActivityを準備する。

ClickTest1

Activityの実装は以下の通り。
public class MainActivity extends Activity implements View.OnClickListener {
    private Button button1;
    private Button button2;
    private TextView textView1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        button1 = (Button) findViewById(R.id.button1);
        button2 = (Button) findViewById(R.id.button2);
        textView1 = (TextView) findViewById(R.id.textView1);
        button1.setOnClickListener(this);
        button2.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if (v == button1) {
            button2.performClick();
        } else if (v == button2) {
            textView1.setText("Click button2");
        }
    }
}
13行目と14行目で各Button(button1とbutton2)のOnClickListenerとしてMainActivity自らを設定し、18行目からonClickメソッドを実装。
onClickメソッドの中では、button1が押されたらbutton2のperformClickメソッドを実行し、button2が押されたらtextView1に"Click button2"と表示する様にしている。

以上を実行してbutton1を押してみると、

ClickTest2

あたかもbutton2が押されたかの様に動作し、textView1に"Click button2"と表示されている。

このperformClickメソッドは、テスト等で擬似的にButton押下の動作をさせる際に使用できる。


プロフィール

まさお

Author:まさお
プログラミングは趣味レベルなので、お手柔らかに。

ブログランキング
ブログランキング参加中。是非クリックお願いします。


にほんブログ村 IT技術ブログ Androidアプリ開発へ

人気ブログランキングへ

ブログランキング



ブログ王

ブログランキング【ブログの惑星】

プログラム人気ブログランキング
最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム
QRコード
QR
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。