Java8 이후의 Annotation 변화

Bruce Han·2023년 2월 16일
0

Java8-정리

목록 보기
18/20
post-thumbnail

이 포스팅의 코드 및 정보들은 강의를 들으며 정리한 내용을 토대로 작성한 것입니다.

Java8부터 도입된 Annotation의 변화

타입 선언부에도 사용할 수 있다

public @interface Pizza {
}

먼저 휫자 annotation을 선언하고

@Retention(RetentionPolicy.RUNTIME)
public @interface Pizza {
}

Retention 전략을 준다. @Retention은 annotation을 사용한, 그곳에 있는 annotation 정보를 언제까지 유지할 것인가에 대해 지정할 수 있다.

@Retention(RetentionPolicy.RUNTIME)
@Target()
public @interface Pizza {
}

@Target은 annotation을 사용할 곳인데 Java8에는 크게 두 개의 type이 추가됐다.

@Target - ElementType.TYPE_PARAMETER

public static void main(String[] args) {

}

static class FeelsLikePizza<T> {
        
}

FeelsLikePizza<T>가 어떤 특정한 타입을 사용하는, Generic한 클래스라고 정의할 때

annotation

T라고 하는 Function에 정의되어 있는 <T, R>을 Type Parameter, Type Variable이라고 불리우며, 이 Type Parameter 옆에다가 붙일 수 있다.

annotation1

이를 @Target(ElementType.TYPE_PARAMETER), 즉 ElementType.TYPE_PARAMETER 옵션이 허용해주는 것이다.

annotation2

annotation3

@Target(ElementType.TYPE_PARAMETER)가 없어지면 컴파일 에러가 나면서 사용이 제한된다.

어떤 특정한 타입의 인자를 받는 메서드를 하나 만들고 접근 지시자 뒤리턴 타입사이에다가 타입을 지정한다.

annotation4

접근 지시자리턴 타입사이에 있는 Type Parameter인 Cprint()의 파라미터 타입C는 다르다.

annotation5

@Target(ElementType.TYPE_PARAMETER)를 정의했으므로, 접근 지시자리턴 타입사이에 있는 Type Parameter에도 annotation을 붙일 수 있다. 하지만 그냥 메서드의 파라미터 타입 옆에는 붙일 수 없다.

@Target - ElementType.TYPE_USE

ElementType의 TYPE_PARAMETER보다 자유롭게 사용하고 싶을 때 TYPE_USE 옵션을 사용할 수 있다.

TYPE_PARAMETER를 포함해서 Type을 선언하는 모든 곳에 이 annotation을 쓸 수 있게 된다.

annotation6

이렇게 휫자 annotation을 여러군데 놓을 수 있다.

Annotation을 중복해서 사용할 수 있게 됐다

annotation7

지금은 이렇게 휫자를 여러 개 놓으면 컴파일 에러가 발생하지만 @Repeatable을 써서 annotation의 중복을 허용하게 만들 수 있으며, 이는 annotation들을 감싸고 있다고 볼 수 있다.

public @interface PizzaContainer {
}

이 Container annotation type을 @Repeatable에다가 선언해줘야 한다.

annotation8

이때 Container가 가지고 있는 @Retention이나 @Target정보는 반드시 자기 자신이 감싸는 annotation보다 같거나 넓어야 한다. 보통은 같게 만들어 놓는다.

annotation9

설정을 안 해놓거나 범위가 좁으면 이렇게 에러가 난다.

annotation10

이렇게 Container에는 자기 자신이 감싸고 있을 annotation을 배열을 가지고 있으면 된다.

annotation11

Pizza annotation에다가 문자열로 무슨 휫자인지 정의하도록 value()를 하나 선언해놓는다.

annotation12

이렇게 다른 클래스에다가 중복해서 휫자라는 annotation을 선언할 수 있고, 이거를 가져다가 읽어서 쓰기만 하면 된다.

쓰는 방법은

getAnnotationsByType()

첫째로 getAnnotationsByType으로 휫자 타입으로 바로 읽어오는 방법이 있다.

annotation13

이 방법은 타입에 해당하는 다 가져오는데, 여기에서는 두 개의 annotation이 배열로 온다.

getAnnotation()

또는 Container type으로 가져오는 방법이 있는데, 이는 휫자 컨테이너에서 annotation 하나로 가져오면 된다.

annotation14

휫자 컨테이너로 가져온 다음에

annotation15

value()를 통해서 휫자 container의 배열을 꺼내오면 된다.

annotation16

정리

  • annotation에 관련한 두 가지 큰 변화
    • Java 8부터 annotation을 type 선언부에도 사용할 수 있게 됨
    • Java 8부터 annotation을 중복해서 사용할 수 있게 됨
  • 타입 선언 부
    • Generic type
    • Variable type
    • Parameter type
    • Exception type
    • etc
  • 타입에 사용할 수 있으려면
    • TYPE_PARAMETER : 타입 변수에만 사용할 수 있다
    • TYPE_USE : 타입 변수를 포함해서 모든 타입 선언부에 사용할 수 있다ㅇ
  • 중복 사용할 수 있는 annotation 만들기
    • 중복해서 사용할 annotation 만들기
    • 중복 annotation container 만들기
      • container annotation은 중복 annotation과 @Retention 및 @Target이 같거나 더 넓어야 한다
  • 중복 사용할 annotation
// Pizza.java
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_USE)
@Repeatable(PizzaContainer.class)
public @interface Pizza {
	String value();
}
  • 중복 annotation의 container annotation
// PizzaContainer.java
@Rentention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_USE)
public @interface PizzaContainer {
	Pizza[] value();
}
  • container annotation으로 중복 annotation 참조하기
// Main
@Pizza("포테이토")
@Pizza("고구마")
public class Main {
	public static void main(String[] args) {
    	PizzaContainer pizzaContainer = Main.class.getAnnotation(PizzaContainer.class);
        Arrays.stream(pizzaContainer.value()).forEach(c -> {
        	System.out.println(c.value()));
        });
     }
}

Reference

profile
만 가지 발차기를 한 번씩 연습하는 사람은 두렵지 않다. 내가 두려워 하는 사람은 한 가지 발차기를 만 번씩 연습하는 사람이다. - Bruce Lee

0개의 댓글