Подтвердить что ты не робот

Как получить доступ к значению поля в объекте с использованием отражения

Мой вопрос: Как преодолеть IllegalAccessException для доступа к значению поля объекта с помощью отражения.

Расширение: Я пытаюсь узнать об отражении, чтобы сделать некоторые из моих проектов более универсальными. Я запускаю IllegalAccessException при попытке вызвать field.getValue(object), чтобы получить значение этого поля в этом объекте. Я могу получить имя и тип просто отлично.

Если я изменяю объявление от 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)
4b9b3361

Ответ 1

Перед тем, как 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));
}

Ответ 2

По умолчанию вам запрещено читать непубличные поля, но просто вызывать field.setAccessible(true); разрешает доступ. Другими словами, ваш код должен сказать

for (Field field : fields) {
  field.setAccessible(true);
  ....