CodeGym /행동 /All lectures for KO purposes /리플렉션을 이용한 객체의 내부 상태 변경

리플렉션을 이용한 객체의 내부 상태 변경

All lectures for KO purposes
레벨 1, 레슨 701
사용 가능

전용 필드가 있는 클래스

모두 필드 액세스 수정자에 대해 잘 알고 있습니다. 그리고 필드에 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 메서드 를 호출하려고 하면 예외가 다시 발생합니다 .

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

코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION