언어(Language)/Java

[Java] 자바 메타 어노테이션 정리 및 활용

잇트루 2022. 9. 24. 06:00
반응형

메타 어노테이션 (Meta Annotation)

메타 어노테이션은 어노테이션에 붙이는 어노테이션이다. 즉, 사용할 어노테이션을 정의하는 데 사용한다. 메타 어노테이션은 사용할 어노테이션의 적용대상 또는 어노테이션을 유지하는 시간 등을 규정한다.

 

@Target

@Target 어노테이션은 사용할 어노테이션을 적용할 대상을 지정하는 데 사용한다.

@Target 어노테이션의 옵션은 java.lang.annotation.ElementType 에 정의되어 있으며, 이를 사용하기 위해서는 import를 해주어야 한다.

 

@Target 어노테이션의 사용 방법

@Target 어노테이션을 사용하여 지정할 수 있는 옵션과 대상의 타입은 다음과 같다.

 

@Target(ElementType.ANNOTATION_TYPE) : 어노테이션

 

@Target(ElementType.CONSTRUCTOR) : 생성자

 

@Target(ElementType.FIELD) : 필드(멤버 변수, Enum 상수)

 

@Target(ElementType.LOCALVARIABLE) : 지역변수

 

@Target(ElementType.METHOD) : 메서드

 

@Target(ElementType.PACKAGE) : 패키지

 

@Target(ElementType.PARAMETER) : 매개변수(파라미터)

 

@Target(ElementType.TYPE) : 타입(클래스, 인터페이스, Enum)

 

@Target(ElementType.TYPE_PARAMETER) : 타입 매개변수(제네릭과 같은 매개변수)

 

@Target(ElementType.TYPE_USE) : 타입이 사용되는 모든 대상

 

@Target 어노테이션 예제

import java.lang.annotation.Target;
// 다음과 같이 import를 하면, ElementType.TYPE 대신 TYPE로 대체 가능하다
import java.lang.annotation.ElementType.*;
// import java.lang.annotation.ElementType;

@Target({FIELD, TYPE, TYPE_USE}) // 어노테이션 적용대상 FIELD, TYPE
public @interface CustomAnnotation { // 사용자 정의 어노테이션
}

@CustomAnnotation // 적용 대상이 TYPE인 경우
class Main {
    @CustomAnnotation // 적용 대상이 FIELD인 경우
    int num;
}

 

@Documented

@Documented 어노테이션은 어노테이션에 대한 정보가 javadoc으로 작성한 문서에 포함되도록 하는 어노테이션 설정이다.

javadoc는 자바에서 지정한 형태의 주석들을 인식하여 html을 통해 api 문서 형태로 만들어주는 도구이다.

 

자바에서 제공하는 표준 어노테이션과 메타 어노테이션 중에 @Override와 @SuppressWarnings 어노테이션을 제외하고 모든 어노테이션에 @Documented 어노테이션이 적용되어 있다.

import java.lang.annotation.ElementType;

@Documented
@Target(ElementType.Type)
public @interface CustomAnnotation{

}

 

@Inherited

@Inherited 어노테이션은 하위 클래스가 어노테이션을 상속받도록 한다. 즉, @Inherited 어노테이션을 상위 클래스에 붙이면, 하위 클래스도 상위 클래스에 붙은 어노테이션이 동일하게 적용된다.\

@Inherited
@interface CustomAnnotation{
}

@CustomAnnotation
class UpperClass {
}

// @CustomAnnotation 어노테이션을 붙이지 않아도 붙은 것으로 인식
class Cubclass extends UpperClass {
}

 

@Retention

@Retention 어노테이션은 특정 어노테이션의 지속 시간을 결정하는 데 사용한다.

어노테이션에는 세 가지의 지속 시간을 규정할 수 있다. 이를 유지 정책(Retention Policy)이라 한다.

 

유지 정책

@Retention 어노테이션에 유지 세 가지 유지 정책 중 선택하여 지속 시간을 결정할 수 있다.

 

@Retention(RetentionPolicy.정책) 형태로 사용한다.

 

@Retention(RetentionPolicy.SOURCE) : 자바 소스 파일에 존재하는 것으로, 컴파일 이후 클래스 파일이 되면 사라진다.

즉, 클래스 파일이 되기 이전까지 지속된다.

 

@Retention(RetentionPolicy.CLASS) : 클래스 파일까지는 존재하지만, 실행할 때 사용하지는 않는다. 즉, 런타임이 실행되기 전까지만 존재한다. (기본값)

 

@Retention(RetentionPolicy.RUNTIME) : 클래스 파일까지 존재하며, 실행 시 사용한다. 즉, 지속 시간이 가장 길다.

 

각각의 유지 정책이 활용된 어노테이션의 코드를 살펴보면 다음과 같다.

 

@Override 어노테이션의 정의 (SOURCE)

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

@Override 어노테이션의 유지 정책은 SOURCE이다.

@Override 어노테이션은 오버라이딩이 제대로 되었는지 확인하는 용도로 클래스 파일에 남길 필요 없이 컴파일 시에만 확인하고 사라진다.

 

@NonNull 어노테이션의 정의 (CLASS)

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE, ElementType.TYPE_USE}))
@Retention(RetentionPolicy.CLASS)
public @interface NonNull {
}

롬복(Lombok)의 @NonNull 어노테이션의 유지 정책은 CLASS이다.

따라서 클래스 파일까지는 존재 하지만, 실행할 때는 사용되지 않는다.

 

@Deprecated 어노테이션의 정의 (RUNTIME)

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, MODULE, PARAMETER, TYPE})
public @interface Deprecated {
    /**
     * Returns the version in which the annotated element became deprecated.
     * The version string is in the same format and namespace as the value of
     * the {@code @since} javadoc tag. The default value is the empty
     * string.
     *
     * @return the version string
     * @since 9
     */
    String since() default "";

    /**
     * Indicates whether the annotated element is subject to removal in a
     * future version. The default value is {@code false}.
     *
     * @return whether the element is subject to removal
     * @since 9
     */
    boolean forRemoval() default false;
}

@Deprecated 어노테이션의 유지 정책은 RUNTIME이다.

@Deprecated 어노테이션은 필드나 메서드의 사용을 권장하지 않도록 하는 어노테이션이다.

@Deprecated 어노테이션은 런타임 시에도 사용되며, 실행 후 특정 메시지를 나타내기도 한다.

 

@Repeatable

@Repeatable 어노테이션은 어노테이션을 반복하여 사용할 수 있도록 허용하는 어노테이션이다.

 

@Repeatable을 허용하는 사용자 정의 어노테이션을 만들었다고 가정한다.

@Repeatable(CustomAnnotation.class)
@interface CustomAnnotation {
    String value();
}

 

다음과 같이 사용자 정의 어노테이션을 만들면, 해당 어노테이션을 여러 번 사용할 수 있게 된다.

@CustomAnnotation("Hello")
@CustomAnnotation("Java")
@CustomAnnotation("World")
class Test {
}

 

또한, @Repeatable 어노테이션은 일반적인 어노테이션과 달리 같은 이름의 어노테이션이 여러 번 적용될 수 있다. 따라서, 하나로 묶어주는 어노테이션을 별도로 지정해야 한다.

@interface CustomAnnotation2 {
    CustomAnnotation1[] value(); // value()를 여러 개 담을 수 있는 어노테이션
}

@Repeatable(CustomAnnotation2.class) // 컨테이너 어노테이션 지정
@interface CustomAnnotation1 {
    String value();
}
반응형