# 애노테이션의 변화
목차
# 1. 애노테이션 관련 두가지 큰 변화
- 자바 8부터 애노테이션을 타입 선언부에도 사용할 수 있게 됨
- 자바 8부터 애노테이션을 중복해서 사용할 수 있게 됨
# 1-1. 타입 선언 부
- 제네릭 타입
- 변수 타입
- 매개변수 타입
- @Target(ElementType.TYPE_PARAMETER)
- 예외 타입
- etc
# 1-1-1. @Target 설정
타입에 애노테이션을 사용하기 위해 아래와 같은 ENUM 타입을 명시해야 함.
TYPE_PARAMETER
: 타입 변수에만 사용할 수 있다.TYPE_USE
: 타입 변수를 포함해서 모든 타입 선언부에 사용할 수 있다.
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
TYPE,
/** Field declaration (includes enum constants) */
FIELD,
/** Method declaration */
METHOD,
/** Formal parameter declaration */
PARAMETER,
/** Constructor declaration */
CONSTRUCTOR,
/** Local variable declaration */
LOCAL_VARIABLE,
/** Annotation type declaration */
ANNOTATION_TYPE,
/** Package declaration */
PACKAGE,
/**
* Type parameter declaration
*
* @since 1.8
*/
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
*/
TYPE_USE
}
@Retention(RetentionPolicy.RUNTIME) // 이 애노테이션 정보를 언제까지 유지할 것인가
@Target(ElementType.TYPE_PARAMETER) // 이 애노테이션을 사용할 곳
public @interface Chicken {
}
public class App {
public static void main(@Chicken String[] args) throws @Chicken RuntimeException {
List<@Chicken String> names = Arrays.asList("Park");
}
// @Target(ElementType.TYPE_PARAMETER) parameter 만 사용
static class FeelsLikeChicken<@Chicken T> {
}
// @Target(ElementType.TYPE_USE) 사용
static class FeelsLikeChicken2<@Chicken T> {
// 전자의 <C> 는 타입 파라미터
// 후자의 C 는 타입
public static <@Chicken C> void print(@Chicken C c) {
System.out.println(c);
}
}
}
# 1-2. 중복 사용할 수 있는 애노테이션을 만들기
- 중복 사용할 애노테이션 만들기
- 중복 애노테이션 컨테이너 만들기
- 컨테이너 애노테이션은 중복 애노테이션과
@Retention
및@Target
이 같거나 더 넓어야 한다.
- 컨테이너 애노테이션은 중복 애노테이션과
# 1-2-1. 중복사용할 애노테이션 생성
/*
@Target(ElementType.TYPE_PARAMETER)
- 제네릭을 사용할 때 타입 변수 앞에 애노테이션을 사용할 수 있다.
@Target(ElementType.TYPE_USE)
- 타입 변수를 포함해서 타입 선언부에서 애노테이션을 사용할 수 있다.
@Repeatable(컨테이너 성격의 애노테이션 class)
- 여러 개의 애노테이션을 가지고 있을 컨테이너 애노테이션을 설정해주면 반복해서 애노테이션 사용이 가능하다.
- 컨테이너의 애노테이션 설정(Retention, Target)은 반드시 자기자신이 감싸는 애노테이션의 범위보다 같거나 넓어야 한다.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_USE)
@Repeatable(ChickenContainer.class)
public @interface Chicken {
String value() default "후라이드";
}
# 1-2-2. 중복 애노테이션의 컨테이너 생성
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_USE)
public @interface ChickenContainer {
// 컨테이너 애노테이션은 자기 자신이 감쌀 애노테이션 배열을 가지고 있어야 한다.
Chicken[] value();
}
# 1-2-3. 컨테이너 애노테이션으로 중복 애노테이션 참조
@Chicken
@Chicken("양념")
@Chicken("마늘간장")
public class App {
public static void main(String[] args) {
// 1. 클래스에서 해당 애노테이션 타입으로 바로 읽어오는 방법
Chicken[] chickens = App.class.getDeclaredAnnotationsByType(Chicken.class);
Arrays.stream(chickens)
.forEach(c -> System.out.println(c.value()));
//2. 컨테이너 애노테이션 타입으로 읽는 방법
ChickenContainer chickenContainer = App.class.getAnnotation(ChickenContainer.class);
Arrays.stream(chickenContainer.value())
.forEach(c -> System.out.println(c.value()));
}
}
@Chicken
은 default value가 없으면 에러가 발생한다.