[Java] 31. Reflection機能を使う方法(Variable編)


Study / Java    作成日付 : 2019/09/20 22:34:40   修正日付 : 2021/04/22 10:48:03

こんにちは。明月です。


この投稿はJavaのReflection機能を使う方法(Variable編)に関する説明です。


以前の投稿でJavaのReflection機能をClassとMethodを分けて説明しました。

link - [Java] 29. Reflection機能を使う方法(Class編)

link - [Java] 30. Reflection機能を使う方法(Method編)


ClassとMethodにはStringでクラスやメソッドを探して割り当てすることや呼び出すことが重要なReflection機能でした。

このVariableでも別に違う機能があることではありません。


メンバー変数はOOPの特性でprivateのアクセス修飾子によりカプセル化します。

link - [Java] 14. オブジェクト指向プログラミング(OOP)の4つ特性(カプセル化、抽象化、継承、多相化)


普通はクラス内部でReflectionを利用して変数の値を取得することではないです。なので別に必要性がありません。

でも、クラスの外部でクラスの変数値を取得したい場合は?privateになっているから取得できないです。それがOOPの特性なので。

import java.lang.reflect.Field;
class Node {
  // privateタイプ
  private int data = 0;
  // メンバー変数設定
  public void setData(int data) {
    this.data = data;
  }
  // メンバー変数リターン
  public int getData() {
    return this.data;
  }
}
public class Example {
  // 実行関数
  public static void main(String... args) {
    try {
      // インスタンス生成
      Node node = new Node();
      // Reflectionでdata変数を取得する。
      Field field = Node.class.getDeclaredField("data");
      // setAccessibleはprivate、protectedタイプもアクセス可能にする。
      field.setAccessible(true);
      // dataフィールドに100を格納
      field.set(node, 100);
      // 結果は100が出力
      System.out.println(node.getData());
    } catch (Throwable e) {
      e.printStackTrace();
    }
  }
}


上の例をみればNodeインスタンスを生成してgetDeclaredField関数でデータ値を取得します。

setAccessibleの関数はprivateの時にアクセスが可能にする関数です。


実はmainではNodeインスタンスのメンバー変数はprivateなのでアクセスができないです。

でも、上の例ではprivateになっているメンバー変数のデータを取得しました。そしてデータを格納することまでしました。

つまり、Reflectionを利用すればUnitテストのプログラムを作成する時、関数の結果だけではなく、途中のクラスのデバッグ値やメンバー変数の値を確認することができます。

import static org.junit.Assert.*;
import java.lang.reflect.Field;
import org.junit.Test;
class Node {
  // privateタイプ
  private int data = 0;
  // メンバー変数の値を設定
  public void setData(int data) {
    this.data = data;
  }
  // メンバー変数の値をリターン
  public int getData() {
    return this.data;
  }
}
public class TestCase {
  // Unitテストを設定
  @Test
  public void test() {
    try {
      // インスタンス生成
      Node node = new Node();
      // dataフィールドに100を格納
      node.setData(100);
      // Reflectionでdata変数を取得する。
      Field field = Node.class.getDeclaredField("data");
      // setAccessibleはprivate、protectedタイプもアクセス可能にする。
      field.setAccessible(true);
      // データ検証
      assertEquals(field.get(node), 100);
    } catch (AssertionError e) {
      throw e;
    } catch (Throwable e) {
      e.printStackTrace();
    }
  }
}


Reflectionのメソッドでもありますが、変数にもクラスの変数リストを取得する関数があります。

MethodではgetDeclaredMethods関数が呼ばされたクラスだけ、 getMethods関数は親クラスまでの関数がリストに出力されます。

変数は少し違いです。getDeclaredFieldsとgetFieldsの差異はgetDeclaredFieldsはprivateの含め変数、getFieldsはpublicだけの変数です。

普通のクラスはカプセル化になっているので、getFields関数は使うことではないですね。

リストだけではなく、変数名で取得する関数ても同じです。つまり、privateの変数をgetFieldに取得するとnullになります。こちらも変数がprivateタイプになっているのでgetDeclaredFieldだけ使うことになります。


ここまでJavaのReflection機能を使う方法(Variable編)に関する説明でした。


ご不明なところや間違いところがあればコメントしてください。

Study / Java」の他投稿
最新投稿