본문 바로가기

Java/Java

(JAVA) 리플렉션 API(2) - 애노테이션과 리플렉션

중요 애노테이션

애노테이션 생성

public @interface MyAnnotation {
    
}
@MyAnnotation
public class Book {

 

Book 클래스에 애노테이션이 잘 달려있는지 확인해보자!

Arrays.stream(bookClass.getAnnotations()).forEach(System.out::println);

어!! 아무것도 안나오네?!?!

왜지!??! 바이트코드에도 없나?

 

 

javap -c -v /Applications/개발환경/repository/PURE_JAVA/Reflectionstudy/Refactoring/target/classes/me/choi/Book.class

(바이트코드에 애노테이션 정보까지 보고 싶으면 -v 명령어를 사용)

invisible이라고 해당 어노테이션을 볼 수 없다고 나와있다.

그럼 왜 안보이는 걸까?

 

애노테이션은 주석과 같은 취급을 받는다.

소스와 클래스에는 정보가 남지만 바이트코드를 로딩하였을때 메모리 상에는 남지않기 때문이다.


나는 런타임까지 애노테이션 정보를 가져가고 싶어!

@Retention의 활용 : 기본값은 Class

 

@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {

}

실행결과 해당 애노테이션이 출력된걸 볼 수 있다.
visible이라고 해당 어노테이션을 볼 수 있다고 나와있다.


 애노테이션을 사용할 자리를 지정하고 싶어!

@Target({ElementType.TYPE, ElementType.FIELD})

애노테이션으로 값 값을 지정하고 싶어!

 

기본 사용방법

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD})
public @interface MyAnnotation {

    String name();

    int number();


}
@MyAnnotation(name = "choi", number = 29)

 

Default 사용 : 기본 값을 설정하였다면 사용 시 값을 명시할 필요가 없다.

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD})
public @interface MyAnnotation {

    String name() default "choi";

    int number() default 29;


}
@MyAnnotation
public class Book {

 

value 사용 : key값을 명시하지 않고  값만 쓰면된다. - 값을 한 개만 받을 때 조금 더 간결하게 표현가능

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD})
public @interface MyAnnotation {

    String value();
    
}
@MyAnnotation("choi")
public class Book {

 

부모클래스의 애노테이션까지 가져오고 싶어! (@Inherited)

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD})

@Inherited
public @interface MyAnnotation {

    String value();

}

 

현재 MyBook은 Book을 상속받는다. 

해당 어노테이션을 사용했을때 Book의 애노테이션 까지 출력이 됨을 확인할 수 있다.

public class MyBook extends Book implements Myinterface{

}

 

Arrays.stream(MyBook.class.getAnnotations()).forEach(System.out::println);

 

실행결과

@Inherited를 사용하더라도 지금 현재 자신의 클래스에 붙어있는 애노테이션만을 가져오고 싶을때는

getDeclaredAnnotations 를 사용!

 

Arrays.stream(MyBook.class.getDeclaredAnnotations()).forEach(System.out::println);

애노테이션의 값을 가지고 오고싶어!

Arrays.stream(bookClass.getAnnotations()).forEach(f -> {
    if(f instanceof MyAnnotation) {
        MyAnnotation myAnnotation = (MyAnnotation) f;
        System.out.println(myAnnotation.value());
        System.out.println(myAnnotation.number());
    }
});

 실행결과

 

  • @Retention: 해당 애노테이션을 언제까지 유지할 것인가? 소스, 클래스, 런타임

  • @Inherit: 해당 애노테이션을 하위 클래스까지 전달할 것인가?

  • @Target: 어디에 사용할 수 있는가?


Code Link

https://github.com/mike6321/PURE_JAVA/tree/master/Reflectionstudy

 

mike6321/PURE_JAVA

Contribute to mike6321/PURE_JAVA development by creating an account on GitHub.

github.com