Engineering Note

プログラミングなどの技術的なメモ

リフレクションからフィールドにアクセスする

privateで宣言されたフィールドは、getterやsetterがないとアクセスすることはできませんが、Javaの標準APIであるリフレクションを使用するとアクセスが可能となります。

ただ、これを使用してしまうと何のためにアクセス制御(カプセル化)をしているのか意味がなくなってしまうので、テストをする際にどうしてもモック化が必要であった場合等に重宝します。

 

まずは、以下のようにprivateなフィールドをコンストラクタのみのクラスがあったとします。

 

 // TestField.java
public class TestField {
    private String value;

    public TestField(String value) {
        this.value = value;
    }
}

 

通常では、どうやってもvalue値を取得したりセットしたりすることはできませんが、

以下のようにリフレクションを使用するとそれが可能となります。

 

 // Test.java
import java.lang.reflect.Field;

public class Test {
    public static void main(String[] args) {
        TestField test = new TestField("foo");
        
        try {
            Field field = test.getClass().getDeclaredField("value");
            //フィールドにアクセスできるようにする
            field.setAccessible(true);
            // フィールドの値を取得
            String value = String.valueOf(field.get(test));

            System.out.println(value);

            // フィールドの値を変更
            field.set(test, "bar");
            value = String.valueOf(field.get(test));

            System.out.println(value);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

 

一つ注意点としては、上記のfield.setAccessible(true);を記述しないとフィールドへのアクセスはできず

IllegalAccessExceptionがスローされてしまうので、忘れずに記述しましょう。

 

参考書籍

Java本格入門 ~モダンスタイルによる基礎からオブジェクト指向・実用ライブラリまで