web-dev-qa-db-ja.com

リフレクションを使用してオブジェクトのフィールドの値にアクセスする方法

私の質問:IllegalAccessExceptionを克服して、リフレクションを使用してオブジェクトのフィールドの値にアクセスする方法。

Expansion:いくつかのプロジェクトをより一般的にするために、リフレクションについて学ぼうとしています。 field.getValue(object)を呼び出してそのオブジェクトのそのフィールドの値を取得しようとすると、IllegalAccessExceptionにぶつかります。名前とタイプを取得できます。

宣言をprivateからpublicに変更すると、正常に機能します。しかし、カプセル化の「ルール」に従う努力において、私はこれをしたくありません。どんな助けも大歓迎です!ありがとう!

マイコード:

package main;

import Java.lang.reflect.Field;

public class Tester {

  public static void main(String args[]) throws Exception {
    new Tester().reflectionTest();
  }

  public void reflectionTest() throws Exception {
    Person person = new Person("John Doe", "555-123-4567", "Rover");
    Field[] fields = person.getClass().getDeclaredFields();
    for (Field field : fields) {
      System.out.println("Field Name: " + field.getName());
      System.out.println("Field Type: " + field.getType());
      System.out.println("Field Value: " + field.get(person));
      //The line above throws: Exception in thread "main" Java.lang.IllegalAccessException: Class main.Tester can not access a member of class main.Tester$Person with modifiers "private final"
    }
  }

  public class Person {

    private final String name;
    private final String phoneNumber;
    private final String dogsName;

    public Person(String name, String phoneNumber, String dogsName) {
      this.name = name;
      this.phoneNumber = phoneNumber;
      this.dogsName = dogsName;
    }
  }
}

出力:

run:
Field Name: name
Field Type: class Java.lang.String
Exception in thread "main" Java.lang.IllegalAccessException: Class main.Tester can not access a member of class main.Tester$Person with modifiers "private final"
    at Sun.reflect.Reflection.ensureMemberAccess(Reflection.Java:95)
    at Java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.Java:261)
    at Java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.Java:253)
    at Java.lang.reflect.Field.doSecurityCheck(Field.Java:983)
    at Java.lang.reflect.Field.getFieldAccessor(Field.Java:927)
    at Java.lang.reflect.Field.get(Field.Java:372)
    at main.Tester.reflectionTest(Tester.Java:17)
    at main.Tester.main(Tester.Java:8)
Java Result: 1
BUILD SUCCESSFUL (total time: 0 seconds)
38
kentcdodds

プライベートフィールドをgetする前に、対応するフィールドでsetAccessible(true);を呼び出す必要があります。

for (Field field : fields) {
    field.setAccessible(true); // Additional line
    System.out.println("Field Name: " + field.getName());
    System.out.println("Field Type: " + field.getType());
    System.out.println("Field Value: " + field.get(person));
}
85
Michael Berry

デフォルトでは、非公開フィールドの読み取りは許可されていませんが、field.setAccessible(true);を呼び出すだけでアクセスが許可されます。言い換えれば、あなたのコードは言うべきです

for (Field field : fields) {
  field.setAccessible(true);
  // ...
}
18
Marko Topolnik