Java

Java リフレクションでprivteなフィールドを参照・更新したりメソッドを実行する方法

More than 1 year has passed since last update.

JUnitテストで、privateなフィールドを参照・更新したり、メソッドを実行する必要がありましたので、リフレクションを使ったアクセス方法を整理します。

import java.lang.reflect.Field;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class Test {
static class X {
private int num; // privateな値
private List<String> list; // privateなオブジェクト
private String greeting(String name, int age) { // privateなメソッド
return name + "(" + String.valueOf(age) + "): Hello!";
}
X(int i) {
num = i;
list = new ArrayList<String>();
for (int j = 0; j < i; j++) {
list.add(String.valueOf(j));
}
}
}

public static void main(String[] args) {
X x = new X(10); // privateメンバへアクセスしたいオブジェクト

try {
Class<X> xClass = X.class; // Xクラスのクラスインスタンスを取得

// privateな値の参照と変更
Field xNumField = xClass.getDeclaredField("num");
xNumField.setAccessible(true);
System.out.println(xNumField.getInt(x)); // 10
xNumField.setInt(x, 5); // 5をセット
System.out.println(xNumField.getInt(x)); // 5

// privateなオブジェクトの参照と変更
Field xListField = xClass.getDeclaredField("list");
xListField.setAccessible(true);
List<String> xList = (List<String>)xListField.get(x);
System.out.println(xList); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
xList.add("10");
xListField.set(x, xList); // "10"を追加したリストをセット
System.out.println(xListField.get(x)); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

// privateなメソッドを実行
Class[] argClasses = { String.class, int.class }; // 引数のクラス配列
Method xGreetingMethod = xClass.getDeclaredMethod("greeting", argClasses);
xGreetingMethod.setAccessible(true);
Object[] argObjects = { "Tanaka", 28 }; // 引数のオブジェクト配列
System.out.println(xGreetingMethod.invoke(x, argObjects)); // Tanaka(28): Hello!

} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}