java.lang.reflect.AccessibleObject#setAccessible()の影響範囲
自分は、設定を変更したら元に戻さないときがすまない性分なので、何気なく次のようなコードを書いていた。
private static void printPrivateFieldValue(Object obj, String name) throws Exception { Field field = obj.getClass().getDeclaredField(name); boolean oldAccessible = field.isAccessible(); field.setAccessible(true); try { System.out.println(field.get(obj)); } finally { field.setAccessible(oldAccessible); } }
しかし、そもそもgetDeclaredField()メソッドが返すFieldオブジェクトは同一のものなのだろうか?とふと思い、確認してみることにした。
import java.lang.reflect.Field; public class Main { /** * @param args * @throws Exception */ public static void main(String[] args) throws Exception { Hoge hoge = new Hoge(); Field field1 = hoge.getClass().getDeclaredField("msg"); System.out.println("field(1): " + System.identityHashCode(field1)); System.out.println("field(1): " + field1.isAccessible()); field1.setAccessible(true); System.out.println("field(1): " + field1.isAccessible()); Field field2 = hoge.getClass().getDeclaredField("msg"); System.out.println("field(2): " + System.identityHashCode(field2)); System.out.println("field(2): " + field2.isAccessible()); } }
クラスHogeはこんな感じ。
public class Hoge { private String msg = "Hello World"; public void hoge() { System.out.println(msg); } }
その実行結果。
field(1): 11394033 field(1): false field(1): true field(2): 4384790 field(2): false
どうも、自分の思い込みだったようで。getDeclaredField()メソッドは、その呼び出しごとに異なるFieldオブジェクトを返し、accessibleかどうかの変更に対する影響範囲はそのFieldオブジェクト内に閉じているらしい。
ということで、いちいち変更を元に戻す必要はなく、冒頭のコードは次のように簡潔にできる。
private static void printPrivateFieldValue(Object obj, String name) throws Exception { Field field = obj.getClass().getDeclaredField(name); field.setAccessible(true); System.out.println(field.get(obj)); }