- @Retention : 해당 애노테이션을 언제까지 유지할 것인가? 소스, 클래스, 런타임
- @Inherit : 해당 Annotation을 하위 클래스까지 전달할 것인가?
- @Target : 어디에 사용할 수 있는가?
public @interface MyAnnotation {
}
@MyAnnotation
public class Book {
private static String B = "Book";
private static final String C = "Book";
private String a = "a";
public String d = "d";
protected String e = "e";
public Book() {
}
public Book(String a, String d, String e) {
this.a = a;
this.d = d;
this.e = e;
}
private void f() {
System.out.println("F");
}
public void g() {
System.out.println("G");
}
public int h() {
return 1000;
}
}
public class App {
public static void main(String[] args) {
Arrays.stream(Book.class.getAnnotations()).forEach(System.out::println);
}
}
위와 같이 Book Class의 Annotation을 조회할려고 하면 조회가 되지 않는다. 왜냐하면 Annotation은 주석과 비슷하게 작동되어서 정보가 소스,Class까지는 남지만 바이트코드를 로딩하는 시점에는 남지 않는다. 즉 런타임 시에는 작동되지 않는다.
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
}
때문에 위와 같이 런타임시 까지 유지되도록 할려면 위와 같은 @Retention 애노테이션을 붙여주면 된다.

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD})
public @interface MyAnnotation {
}
@Target 애노테이션을 사용해서 Annotation의 위치를 지정할 수 있다.
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD})
public @interface MyAnnotation {
String value();
String name() default "hyun6ik";
int number() default 100;
}
default를 사용해서 기본 값 또한 지정할 수 있다.
또한 value를 지정하면@MyAnnotation("hello") public class Book {위와 같이 명시할 필요없이 바로 사용 가능하다. (parameter가 2개 이상일 시 value= 같이 지정해야한다.)
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD})
@Inherited
public @interface MyAnnotation {
String value();
String name() default "hyun6ik";
int number() default 100;
}
위와 같이 @Inherited 애노테이션을 지정하면 MyAnnotation을 적용한 클래스의 하위 클래스까지도 애노테이션이 적용된다.
public class MyBook extends Book implements MyInterface{
}
public class App {
public static void main(String[] args) {
Arrays.stream(MyBook.class.getAnnotations()).forEach(System.out::println);
}
}

- getAnnotation() : 상속 받은(@Inherit) 애노테이션까지 조회
- getDeclaredAnnotations : 자기 자신에만 붙어있는 애노테이션 조회
Field의 Annotation은 Annotation의 정보를 꺼내서 참조할 수 있다.
Arrays.stream(Book.class.getDeclaredFields()).forEach(f -> {
Arrays.stream(f.getAnnotations()).forEach(a -> {
if (a instanceof AnotherAnnotation) {
final AnotherAnnotation anotherAnnotation = (AnotherAnnotation) a;
System.out.println(anotherAnnotation.number());
System.out.println(anotherAnnotation.name());
}
});
});