동글이기가 레포

애노테이션 정의하는 방법

 

■ 애노테이션이란?


애노테이션은 Java5부터 등장한 기능으로 주석이라는 뜻을 가지고 있다.

그러나 우리가 알고 있는 주석의 의미와는 다르게 인터페이스를 기반으로 한 문법이며
특별한 의미를 부여하거나 기능을 하는 코드를 작성할 수 있다.

■ 애노테이션 정의 방법

 

public @interface Test { ... }


@interface는 애노테이션 타입을 선언하는 키워드이다.

애노테이션 타입 선언을 일반적인 인터페이스(interface) 선언과 구분하기 위해 interface앞에 @를 붙인다.

■ 애노테이션 필드


애노테이션 안에 필드와 같은 요소들을 정의할 수 있다.

- 요소의 타입은 기본형, Striing, enum, 애노테이션, Class만 가질 수 있음
- 매개변수 선언을 할 수 없음
- 예외 선언을 할 수 없음
- 요소를 타입 매개변수로 정의할 수 없음
- 배열 선언 가능
- default 값 지정 가능 / int num() default 10;

public @interface Test { 
    int num() default 10;
    String value();
    String[] arr();
    Class c1();
    Target t();
}


위의 예시에서 기본형, String, 배열, Class, Target 애노테이션을 정의할 수 있었다.

그러한 요소들을 아래와 같이 적용하여 사용할 수 있다.

public class Main {
    @Test( value = "Hello",
           arr = {"aaa", "bbb", "ccc"},
           cc = Main.class,
           t = @Target(ElementType.ANNOTATION_TYPE))
    public void method() { }
    public static void main(String[] args) { } 
}

 

■ 빌트인 애노테이션


Java에 내장되어 있는 애노테이션

1. @Override

현재 메소드가 슈퍼 클래스의 메소드를 재정의한 것을 컴파일러에게 명시
메소드에 슈퍼 클래스가 없으면 에러를 발생

2. @Deprecated


마커 애노케이션으로 미리 만들어져 있는 클래스나 메소드가 더 이상 사용되지 않는 경우 경고를 알린다.

주로 버전의 차이때문에 발생한다.

3. @SuppressWarning


경고를 제거하는 애노테이션으로 개발자가 의도를 가지고 설계를 했는데, 컴파일러는 이를 알지 못하고 컴파일 경고를 띄을 수 있기 때문에 이것을 제거하는 목적으로 사용한다.

4. @SafeVarargs


Java 7 이상에서 사용가능하며, 제네릭과 같은 가변인사 매개변수 사용 시 경고를 무시한다.

5. Functionalinterface


Java 8 이상에서 사용 가능하고, 컴파일러에게 함수형 인터페이스라는 것을 알린다.

※ 함수형 인터페이스는 1개의 추상 메소드만 가지고 있는 인터페이스로 지난 번에 배운 Runnable이 있다.


메타 애노테이션(@Retention, @Target, @Documented)

 

@Retention


애노테이션이 유지되는 기간인 Life Time을 설정하는 애노테이션이다.

@Documented 
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE) 
public @interface Retention { 
    RetentionPolicy value(); 
} 


// 아래는 RetentionPolicy
public enum RetentionPolicy { 
    SOURCE,
    CLASS,
    RUNTIME 
}


Retention 괄호 안에 지정하는 요소들을 하나씩 살펴보면,

SOURCE : 애노테이션 정보가 컴파일 시 사라짐
CLASS : 디폴드 값으로, 클래스 파일에 있는 애노테이션 정보가 컴파일러에 의해서 참조 가능, 그러나 VM에서는 사라짐
RUNTIME : 실행 시 애노테이션 정보가 VM에 의해서 참조 가능

@Target


애노테이션이 적용 가능한 대상을 지정한다.

만약 다른 타입을 사용하면 에러가 발생한다.

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target { 
    ElementType[] value(); 
}


// 아래는 ElementType public enum ElementType {
    TYPE,
    FIELD,
    METHOD,
    PARAMETER,
    CONSTRUCTOR,
    LOCAL_VARIABLE,
    ANNOTATION_TYPE,
    PACKAGE,
    TYPE_PARAMETER,
    TYPE_USE,
    MODULE,
    ...
}


ElementType을 살펴보자.

■ 기존


- TYPE : Class, Interface, enum, 등
- FIELD : 필드 값, enum 상수 값
- METHOD : 메소드
- PARAMETER : 메소드 파라미터
- CONSTRUCTOR : 생성자
- LOCAL_VARIABLE : 지역변수
- ANNOTATION_TYPE : 애노테이션
- PACKAGE : 자바 패키지

■ jdk 1.8 이후 추가


- TYPE_PARAMETER : 타입 매개변수
- TYPE_USE : 타입 사용 // jdk 9 이후
- MODULE : 모듈

■ jdk 14 이후 추가


- RECORD_COMPONENT : Record 컴포넌트

@Documented


애노테이션 정보가 javadoc으로 작성된 문서에 포함되도록 하는 메타 애노테이션

Java에서 제공하는 기본 애노테이션 중에 @Override와 @SuppressWarnings를 제외하고 모두 @Documented 애노테이션이 붙어 있다.


애노테이션 프로세서

 

■ 애노테이션 프로세서란?


Java 컴파일러의 컴파일 단계에서, 사용자가 정의한 애노테이션의 코드를 분석하고 처리하기 위해 사용되는 훅이다.

컴파일 에러, 경고나 소스코드(.java)와 바이트 코드(.class)를 내보내기도 한다.

■ 사용 예제


1. Lombok(롬복)
- @Getter, @Setter, @Builder

2. AutoService
- java.util.ServiceLoader용 파일 생성 유틸리티
- 리소스 파일을 만들어 줌
- META-INF > service > ServiceLoader용 레지스트리 파일을 생성

3. @Override
- 컴파일러가 오버라이딩하는 메소드가 잘못된 대상임을 체크해주는 행위도 애노테이션 프로세서의 한 종류

4. Dagger2
- 컴파일 타임 DI 제공 -> 런타임 비용이 없어짐

5. 안드로이드 라이브러리
- ButterKnife : @BindView(뷰 아이디와 애노테이션을 붙인 필드 바인딩)
- DeepLinkDispatcher : 특정 URI 링크를 액티비티로 연결할 때 사용

■ 애노테이션 프로세서의 장단점


1. 장점
- 컴파일 시점에서 동작하기 때문에 런타임 비용이 없다.

2. 단점
- 현재 public한 API가 없다

'스터디 > 동기 Java 스터디' 카테고리의 다른 글

9주차 : 제네릭  (0) 2021.05.23
8주차 : I/O  (0) 2021.05.19
7주차 : Enum  (0) 2021.05.13
7주차 : 멀티쓰레드 프로그래밍  (0) 2021.05.10
6주차 : 예외 처리  (0) 2021.05.05

공유하기

facebook twitter kakaoTalk kakaostory naver band
loading