엔지니어로 가는 길

JAVA 어노테이션에 대해 알아보자 본문

프로그래밍/Java

JAVA 어노테이션에 대해 알아보자

탐p슨 2020. 9. 5. 21:19
728x90

출처: http://docs.oracle.com/javase/tutorial/java/annotations/

annotate

add notes to (a text or diagram) giving explanation or comment.

어노테이션이란

메타데이터의 형식으로 프로그램에 대한 데이터(이는 프로그램의 일부는 아니다)를 제공한다. 어노테이션은 가리키는 코드의 동작에 직접적인 영향을 미치지는 않는다.

어노테이션의 용도

컴파일러을 위한 정보 제공

어노테이션은 에러를 잡아내거나 경고를 무시하기 위해 컴파일러에 의해 사용될 수 있다.
컴파일 타임, 개발 타임 처리

소프트웨어 도구는 코드, xml 파일 등을 생성하기 위해 어노테이션 정보를 이용할 수 있다.
런타임 처리

일부 어노테이션은 런타임에 사용될 수 있다.

어노테이션의 형태

‘@’는 컴파일러에게 다음에 오는 것이 어노테이션임을 알려주는 문자이다. 어노테이션의 가장 단순한 형태는 아래와 같다.

 


어노테이션은 elements를 가질 수 있다. elements는 이름을 가질 수도, 가지지 않을 수도 있다. elements는 값을 가진다. 다음은 elements를 가지는 어노테이션을 사용하는 예시이다.

 


만약 value라는 이름의 element 하나만 있다면 element의 이름은 생략될 수 있다.


같은 곳에 여러 개의 어노테이션을 붙일 수도 있다.

 


같은 곳에 붙은 어노테이션들이 같은 타입을 가지는 경우 이 어노테이션을 repeating 어노테이션이라고 한다. (repeating 어노테이션은 자바8부터 지원된다.)

 

어노테이션의 타입은 java.lang 또는 java.lang.annotation 패키지에 정의된 타입중 하나일 수 있다. 예시로 등장했던 Override와 SuppressWarnings는 미리 정의된 자바 어노테이션이다. 원한다면 자신만의 어노테이션 타입을 정의할 수 있다. 예시로 등장했던 Author와 Ebook이 커스텀한 어노테이션 타입이다.

어노테이션의 위치

어노테이션은 declarations(클래스, 필드, 메소드, 다른 프로그램의 elements의 declarations)에 적용될 수 있다. (자바8부터 어노테이션을 type use에도 붙일 수 있는데 이건 다음에 좀 더 자세히 살펴보도록 한다.) 코드 한 줄에 어노테이션 하나만 있도록 하는 것이 관례이다.

어노테이션 사용 예시

모든 클래스마다 아래와 같이 주석을 달아야 한다고 가정해보자.

 


위와 같은 메타 정보를 제공하기 위해서는 먼저 어노테이션 타입을 정의해야 한다. 문법은 아래와 같다.


-어노테이션의 정의는 interface 키워드 앞에 ‘@’ 문자를 붙여주면 된다.

-어노테이션의 body는 어노테이션 타입 element declarations를 갖는다. 메소드처럼 생겼다. element에 defulat 값을 지정해줄 수 있다는 점을 기억하자.

-어노테이션 타입을 정의한 뒤에는 그 타입의 어노테이션을 사용할 수 있다. default 값이 지정되지 않은 경우 값을 주어야 한다.

미리 정의된 어노테이션 타입

자바 API에 많은 어노테이션들이 미리 정의되어 있다. 일부 어노테이션은 자바 컴파일러에 의해 사용되며, 일부 어노테이션은 다른 어노테이션에 적용된다. java.lang에 정의된 어노테이션은 @Deprecated와 @Override 그리고 @SuppressWarnings이다.

 

@Deprecated 이 어노테이션은 더이상 사용하지 않기를 권고하는 element에 붙인다. 이 어노테이션이 붙은 메소드나 클래스 또는 필드를 사용하면 컴파일러가 경고한다. element가 deprecated될 때 아래와 같이 Javadoc @deprecated 태그를 통해 문서화되어야 한다.


Javadoc 태그는 소문자로, 어노테이션은 대문자로 시작한다는 점에 주의하자.

@Override 수퍼 클래스의 element를 오버라이드한다고 컴파일러에게 알리는 어노테이션이다. 오버라이드를 할 때 반드시 이 어노테이션을 붙여야 하는 것은 아니지만 이 어노테이션을 붙이면 에러를 예방할 수 있다. 이 어노테이션이 붙었는데 부모의 element를 정확하게 오버라이드하지 않는 경우 컴파일러가 에러를 발생시켜주기 때문이다.

@SuppressWarnings 컴파일러에게 특정 경고(이 어노테이션을 붙이지 않았으면 발생했을)를 무시하라고 말하고 싶을 때 붙이는 어노테이션이다. 


모든 컴파일러의 경고는 두 개의 카테고리에 속한다. deprecation와 unchecked이다. unchecked는 제네릭스가 등장하기 전에 쓰인 레거시 코드를 만났을 때 발생할 수 있다. 여러 경고를 무시하고 싶다면 아래와 같이 배열로 주면 된다.


@SafeVarargs 이 어노테이션이 메소드나 생성자에 적용되면, 코드가 가변인자 매개변수에 대한 잠재적으로 안전하지 않은 연산을 수행하지 않는다는 것이 보장된다. 따라서 이 어노테이션이 사용되면 가변인자의 사용과 관련된 unchecked 경고가 무시된다.

@FunctionalInterface 자바8부터 도입된 어노테이션으로 functional 인터페이스임을 가리킨다. @Override와 마찬가지로 functional 인터페이스에 반드시 붙여야 하는 것은 아니지만 붙일 경우 에러를 예방할 수 있다(메소드가 두 개 이상이되면 컴파일러가 functional 인터페이스가 아님을 감지하고 에러를 발생시킨다).

 

메타 어노테이션(다른 어노테이션에 사용되는 어노테이션)

다른 어노테이션에 적용되는 어노테이션을 meta-annotations라 한다. 다음은 java.lang.annotation에 정의된 몇몇 meta-annotation이다.

@Retention 어노테이션을 어떻게 저장할지를 명시하는 어노테이션이다. 이 어노테이션은 value라는 element에 RetentionPolicy 타입을 줄 수 있다.

 

 

RetentionPolicy.SOURCE: 소스 레벨에서만 유지되고 컴파일러에게는 무시된다(주석과 다를바 없다).
RetentionPolicy.CLASS: 컴파일 타임까지 살아남지만 JVM에게는 무시된다.
RetentionPolicy.RUNTIME: JVM까지 볼 수 있도록 유지된다. 따라서 런타임 환경에 사용될 수 있다.

@Documented 이 어노테이션이 사용될 때마다 elements가 Javadoc 도구에 의해 문서화되어야 함을 나타낸다. (디폴트 설정을 따르면 어노테이션은 Javadoc에 포함되지 않는다.)

@Target 어떤 Java elements에 적용될 수 있는지를 나타내는 어노테이션이다. value라는 이름의 element에 아래와 같은 ElementType이 올 수 있다.

ElementType.ANNOTATION_TYPE can be applied to an annotation type.
ElementType.CONSTRUCTOR can be applied to a constructor.
ElementType.FIELD can be applied to a field or property.
ElementType.LOCAL_VARIABLE can be applied to a local variable.
ElementType.METHOD can be applied to a method-level annotation.
ElementType.PACKAGE can be applied to a package declaration.
ElementType.PARAMETER can be applied to the parameters of a method.
ElementType.TYPE can be applied to any element of a class.

@Inherited 어노테이션 타입이 수퍼 클래스로부터 상속될 수 있음을 나타낸다. 디폴트 설정은 false이다. 예시를 들어보자.

 

http://stackoverflow.com/questions/23973107/how-to-use-inherited-annotation-in-java/23973331

 

InheritedAnnotationType는 @Inherited가 붙은 어노테이션이다.

UninheritedAnnotationType 는 안붙은 어노테이션이다.

 

클래스 B를 확인해보면 클래스 A를 상속받고 있지만 UninheritedAnnotationType 어노테이션을 가지고 있지 않다. UninheritedAnnotationType은 @Inherited가 붙지 않아 상속되지 않은 것이다.

 

클래스 C를 확인해보면 클래스 B를 상속받고 있는데 InheritedAnnotationType 어노테이션을 가지고 있다. C에는 아무 어노테이션도 안붙어 있는데, 수퍼 클래스인 B에서 @Inherited가 붙은 InheritedAnnotationType 어노테이션을 가지고 있어 상속되었다.

 

이 어노테이션은 오직 클래스 declarations에만 적용된다.

 

@Repeatable 자바8부터 도입되었다. 이 어노테이션 붙은 어노테이션은 같은 declaration 또는 type use(자바8부터 type use에도 어노테이션이 붙을 수 있게 되었다)에 한 번 이상 적용될 수 있다. (이것도 다음에 살펴보자.)

 

728x90
Comments