JAVA5에서 제공하는 기본 어노테이션이 3개뿐인데, 여기저기 사용되는 코드를 보면 그 어노테이션의 수가 거의 무한대다. 처음엔 이걸 다 어떻게 익히라는거야? 라는 무식한 생각을 하게되었다. 나중에 알고보니 직접 만든 어노테이션이란거. interface, class만들어 사용하듯 annotation도 직접 만들어 사용가능하다. (당연한얘긴가? 그렇지 않을수도...)

어노테이션 vs 어노테이션 유형 = 클래스의 인스턴스 vs 클래스 로 비교하면 이해가 빠르다.
어노테이션 유형은 인터페이스와 유사하지만 interface선언앞에 "@"가 붙는다. 또 실제로 새로운 어노테이션은 인터페이스를 만드는 것과 많은 부분 같다.

1. 기본 어노테이션

샘플1. 어노테이션 유형 만들기
package com.xxx.xxx;
public @interface TODO{ String value(); }

샘플2. 어노테이션 유형 사용하기

import  com.xxx.xxx.TODO;

@TODO("Figure out the amount of interest per month")  ==============a.
public void calculateInterest(float amount, float rate) {
  // Need to finish this method later
}
위의 사용형태는 아래와 같이 사용해도 된다.
@TODO(value="Figure out the amount of interest per month")
멤버변수가 한개일경우엔 "value =" 부분 없이 바로 사용이 가능하다.




2. Default 값을  가지는 어노테이션 유형

샘플3. Defautl값을 가지는 어노테이션 유형 만들기
package com.xxx.xxx;
public @interface GroupTODO {
  public enum Severity { CRITICAL, IMPORTANT, TRIVIAL, DOCUMENTATION };
  Severity severity() default Severity.IMPORTANT;
  String item();
  String assignedTo();
  String dateAssigned();
}
위의 어노테이션 유형은 아래와 같이 사용한다.

샘플4. Default값을 가지는 어노테이션 사용하기
import com.xxx.xxx;
@GroupTODO(item="Figure out the amount of interest per month", 
    assignedTo="Brett McLaughlin",
    dateAssigned="08/04/2004"
 )
public  void calculateInterest(float amount, float rate) {
    // Need to finish this method later
}
위의 경우는 DEFAULT값을 사용할 경우 severity부분을 생략한 것이고 아래는 DEFAULT이외의 값을 사용해야하기에 severity를 표기한 것이다.

샘플5. Default이외의 값을 가지는 어노테이션 사용하기
import com.xxx.xxx;
@GroupTODO( severity=GroupTODO.Severity.DOCUMENTATION,
    item="Figure out the amount of interest per month", 
    assignedTo="Brett McLaughlin",
    dateAssigned="08/04/2004"
 )
public  void calculateInterest(float amount, float rate) {
    // Need to finish this method later
}


3. Target지정하기

어노테이션 유형을 만들때 Target을 지정할수가 있다. Target을 지정함으로 어노테이션유형이 잘못 사용되는것을 방지할수 있다. Target을 지정하려면 먼저 ElementType을 알아야 한다. java.lang.annotation.ElementType enum 클래스에는 TYPE, FIELD, METHOD, PARAMETER, CONSTRUECOR, LOCAL_VARIABLE, ANNOTATION_TYPE, PACKAGE의 종류가 있다.

샘플6. Target 사용예
 @Target({ElementType.TYPE,
         ElementType.METHOD,
         ElementType.CONSTRUCTOR,
         ElementType.ANNOTATION_TYPE})
public @interface TODO {
  String value();
}


4. Retention 설정 (*retentions 의 사전적 의미는 : 보존, 보유, 감금, 보존력 )

자바 컴파일러가 어노테이션 유형을 다루는 관련 방법을 표시

컴파일러 옵션의 종류
  • RUNTIME - 주석이 달린 클래스의 컴파일 된 클래스 파일에 있는 어노테이션을 유지하다가 클래스가 첫 번째로 로딩될 때 이를 읽는다.
  • CLASS - 컴파일 된 클래스 파일에서 어노테이션을 유지하지만 런타임 시 이를 무시한다. (Default 작동법)
  • SOURCE - 지시된 대로 어노테이션을 사용하지만 컴파일 된 클래스 파일에서 이를 버린다.

    세 가지 옵션은 java.lang.annotation.RetentionPolicy에서 SOURCE, CLASS, RUNTIME으로 구분한다.

  • 5. Documented
    기본적으로 어노테이션은 Javadoc에 포함되지 않는다. 하지만 Documented를 사용하면 클래스의 Javadoc에 포함된다. 이를 위해서 Retention의 정책은 RUNTIME으로 지정해야 한다.


    6. Inherited
    자주 사용하지도 않는 혼란을 일으키는 것이므로 참고문서만 보자.

    어노테이션을 잘 사용하면 매우 유용하지만 너무 남용하게 될경우 코드의 가독성을 떨어뜨리게 되므로 신중을 기해 추가해야 한다.