전용 필드가 있는 클래스

모두 필드 액세스 수정자에 대해 잘 알고 있습니다. 그리고 필드에 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); No access to the field
  }
}

우리는 액세스할 수 없습니다나이필드, 하지만 우리는 반영이 있습니다. :) 그리고 그것의 도움으로 우리는 개인 필드에 액세스하고 작업할 수 있습니다.

리플렉션을 사용하여 개체에서 개인 필드 가져오기

getDeclaredFields() 메서드 를 사용하여 클래스의 모든 필드 배열을 가져옵니다 . 작업하고 수정할 수 있는 Field 객체를 반환합니다 .


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;
    }
사적인 나이
공개 별명

getFieldNames 메서드 에서는 클래스에서 두 개의 필드를 가져옵니다. getModifiers 메서드는 필드의 수정자를 반환하고 getName은 해당 이름을 반환합니다. 이제 이 필드를 수정하고 액세스해 보겠습니다. 먼저 공개 필드에서 데이터를 가져오겠습니다.


public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
    Person person = new Person(10, "CodeGym");

    Field field = Person.class.getDeclaredField("nickname");
    String nickname = (String) field.get(person);
    System.out.println(nickname);

    System.out.println(person.nickname);
}
Code체육관
Code체육관

리플렉션의 도움과 개체에 대한 참조를 사용하여 필드에 액세스할 수 있습니다. 모든것이 좋아! 비공개 필드로 이동하겠습니다.

요청된 필드의 이름을 비공개로 변경합니다.나이필드:


public static void main(String[]args)throws NoSuchFieldException, IllegalAccessException {
		Person person = new Person(10, "CodeGym");

    Field field = Person.class.getDeclaredField("age");
    int age =(int)field.get(person);
    System.out.println(age);

    // System.out.println(person.age);
}

생성된 객체를 통한 접근 권한이 없으므로 리플렉션을 사용해 보세요. 오류가 발생합니다.

IllegalAccessException

IllegalAccessException 이 발생합니다 . 내부 내용물을 살펴보겠습니다.

그것을 알아 내려고합시다.

IllegalAccessException은 현재 실행 중인 메서드가 지정된 클래스, 필드, 메서드 또는 생성자.

여기에 있는 메서드도 이 예외를 throw합니다. 이 예외를 피하기 위해 비공개 필드에 액세스하는 특별한 방법을 사용합니다.

setAccessible(부울 플래그)

이 방법을 사용하면 필드 또는 클래스에 대한 보안 액세스 검사를 피할 수 있습니다. 필드에 대해 보안 액세스 검사를 수행할지 여부를 결정하기 위해 메서드에 true 또는 false를 전달할 수 있습니다 . 코드를 수정해 보겠습니다.


public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
    Person person = new Person(10, "CodeGym");

    Field field = Person.class.getDeclaredField("age");
    field.setAccessible(true);

    int age = (int) field.get(person);
    System.out.println("The current value is " + age);
}

결과를 살펴보겠습니다.

현재 값은 10

엄청난! 수업에 대한 정보를 얻었습니다. 또한 새 값을 할당하여 필드를 변경해 보겠습니다.


public static void main(String[]args)throws NoSuchFieldException, IllegalAccessException {
Person person = new Person(10, "CodeGym");

    Field field = Person.class.getDeclaredField("age");
    field.setAccessible(true);

    field.set(person, 19);

    int age =(int)field.get(person);
    System.out.println("The current value is " + age);
}

필드를 변경한 후 다음을 얻습니다.

현재 값은 19입니다.

setAccessible(false) 를 호출해 보겠습니다 .


public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
    Person person = new Person(10, "CodeGym");

    Field field = Person.class.getDeclaredField("age");
    
    field.setAccessible(true);
    field.set(person, 19);
    field.setAccessible(false);

    System.out.println("The current value is " + field.get(person));
}

접근성을 false 로 복원한 후 get 메서드 를 호출하려고 하면 예외가 다시 발생합니다 .

따라서 비공개 필드 로 작업할 때 주의 하고 리플렉션이 매우 강력한 도구임을 잊지 마십시오!