Класс с приватным полем
Каждый из вас отлично знает про модификаторы доступа полей. И если у поля стоит модификатор private, то доступа извне у нас не будет.
public class Person {
private int age;
public String nickname;
public Person(int age, String nickname) {
this.age = age;
this.nickname = nickname;
}
}
Проверим доступность в нашем Main:
public class Main {
public static void main(String[] args) {
Person person = new Person();
System.out.println(person.nickname);
//System.out.println(person.age); нет доступа к полю
}
}
Доступа к полю age у нас нет, но есть рефлексия. И с ее помощью мы можем получить доступ к приватным полям и работать с ними.
Получение приватного поля у объекта через рефлексию
Давай получим массив всех полей нашего класса с помощью метода getDeclaredFileds(). Он возвращает класс Fileds, с которым мы будем дальше работать и преобразовывать:
public static void main(String[] args) {
Field[] fields = Person.class.getDeclaredFields();
List<String> actualFieldNames = getFieldNames(fields);
actualFieldNames.forEach(System.out::println);
}
static List<String> getFieldNames(Field[] fields) {
List<String> fieldNames = new ArrayList<>();
for (Field field : fields)
fieldNames.add(Modifier.toString(field.getModifiers()) + " " + field.getName());
return fieldNames;
}
public nickname
В методе getFieldNames мы получаем два поля из нашего класса. Метод getModifiers возвращает нам модификатор нашего поля, а getName — название. Теперь давай попробуем изменить и получить доступ к этому полю. Сначала попробуем достать данные из публичного поля:
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
Person person = new Person(10, "javaRush");
Field field = Person.class.getDeclaredField("nickname");
String nickname = (String) field.get(person);
System.out.println(nickname);
System.out.println(person.nickname);
}
javaRush
Доступ к полю и с помощью рефлексии, и с помощью обращения к объекту у нас есть. Все отлично! Движемся к приватному полю.
Меняем название поля, которое мы хотим получить, на наше приватное поле age:
public static void main(String[]args)throws NoSuchFieldException, IllegalAccessException{
Person person = new Person(10, "javaRush");
Field field = Person.class.getDeclaredField("age");
int age =(int)field.get(person);
System.out.println(age);
//System.out.println(person.age);
}
У нас нет доступа через созданный экземпляр класса, поэтому пробуем через рефлексию и сталкиваемся с ошибкой:

IllegalAccessException
У нас возникает IllegalAccessException. Давай перейдем внутрь и посмотрим, что внутри:

Пробуем разобраться.
Исключение IllegalAccessException возникает, когда приложение пытается рефлективно создать экземпляр (кроме массива), задать или получить поле или вызвать метод, но выполняемый в данный момент метод не имеет доступа к определению указанного класса, поля, метода или конструктора.
Также тут есть методы, которые выбрасывают это исключение. Чтобы избежать выбрасывания такого исключения, мы будем использовать специальный метод для получения доступа к приватному полю.
setAccessible(boolean flag)
Этот метод позволяет избежать проверки на доступ к полю или методу класса из-за его модификатора доступа. В метод мы можем передать параметр true или false, который определит, необходимы ли нам проверки на доступ к полю. Пробуем исправить наш код:
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
Person person = new Person(10, "javaRush");
Field field = Person.class.getDeclaredField("age");
field.setAccessible(true);
int age = (int) field.get(person);
System.out.println("Текущее значение - " + age);
}
Смотрим на результат:
Отлично, мы получили данные нашего класса. Давай заодно попробуем изменить наше поле, установив в него новое значение:
public static void main(String[]args)throws NoSuchFieldException, IllegalAccessException{
Person person = new Person(10, "javaRush");
Field field = Person.class.getDeclaredField("age");
field.setAccessible(true);
field.set(person, 19);
int age =(int)field.get(person);
System.out.println("Текущее значение - " + age);
}
Пробуем изменить наше поле и получаем результат:
Пробуем выставить setAccessible(false).
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
Person person = new Person(10, "javaRush");
Field field = Person.class.getDeclaredField("age");
field.setAccessible(true);
field.set(person, 19);
field.setAccessible(false);
System.out.println("Текущие значение - " + field.get(person));
}
После возвращения доступа на false мы снова сталкиваемся с нашим исключением, когда пытаемся вызвать метод get:

Поэтому будь осторожен, когда работаешь с private-полями и не забывай, что рефлексия — очень мощный инструмент для работы!
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ