리플렉션

클래스 정보 조회

  • Class<T>라는 타입을 통해 클래스의 모든 정보(ex. 필드, 메서드, 상위 클래스, 인터페이스, 어노테이션, 생성자 등)를 조회할 수 있다.

  • 클래스를 문자열을 통해 읽을 수 있으며, Class.forName("MyClass") 와 같이 사용할 수 있다. 만약 해당 클래스가 없다면 ClassNotFoundException이 발생한다.

어노테이션과 리플렉션

  • @Retention : 어노테이션을 유지하는 기간을 설정한다.

    • SOURCE, CLASS, RUNTIME 속성을 사용 가능하며 기본적으로 RUNTIME 속성이 사용된다.

    • SOURCE 레벨은 말그대로 소스 코드 까지 어노테이션을 유지하는 것이다.

    • CLASS 레벨은 바이트 코드까지 어노테이션을 유지하는 것이다.

    • RUNTIME 레벨은 실제 런타임까지 어노테이션을 유지하는 것으로, 리플렉션으로 어노테이션을 읽으려면 이 속성을 사용해야 한다.

  • @Inherited : 부모 클래스에 어노테이션을 붙였을 때 자식 클래스에도 어노테이션을 적용한다.

  • @Target : 어노테이션을 어디에서까지 사용할 수 있는지 설정한다.

    • TYPE, FIELD, METHOD 등 어느 곳에 어노테이션을 붙일 수 있는지 지정한다.

  • 어노테이션은 primitive 타입 혹은 boxing된 타입을 필드로 가질 수 있다.

public @interface PersonAnnotation {
    String name() default "kim";
    int age() default 20;
}
  • 리플렉션을 통해 어노테이션의 정보를 얻을 수 있다.

PersonAnnotation personAnnotation = Son.class.getAnnotations(); // 상속받은 어노테이션까지 조회
String nameOfSon = personAnnotation.name();
int ageOfSon = personAnnotation.age();

Mom.class.getDeclaredAnnotations(); // 자신 클래스에 붙은 어노테이션만 조회

클래스 정보 수정 및 실행

객체 생성하기

Constructor<NullValue> constructor = NullValue.class.getDeclaredConstructor();
constructor.setAccessible(true); // private일 경우 접근 가능하도록 허용해주어야 한다.
NullValue nullValue = constructor.newInstance();

객체의 필드 조회/수정하기

Book book = (Book) Book.class.getConstructor(String.class).newInstance("myBook");
Field name = Book.class.getDeclaredField("name");
name.setAccessible(true);
String nameOfBook = name.get(book); // 필드 조회하기
name.set(book, "myUpdatedBook"); // 필드 수정하기

메서드 실행하기

Book book = new Book();
Method setTotalPages = book.getClass().getDeclaredMethod("setTotalPages", long.class);
setTotalPages.setAccessible(true); // private일 경우 접근 가능하도록 허용해주어야 한다.
setTotalPages.invoke(book, 150);

주의점

  • 지나친 사용은 성능 이슈를 야기할 수 있으니 반드시 필요한 경우에만 사용해야 한다.

  • 컴파일 타임에 확인되지 않은 문제가 런타임에 발생할 수 있다.

  • 접근 지시자를 무시할 수 있다.

Last updated