Java : Annotation

unchapterd·2021년 11월 1일
0

Java

목록 보기
12/19
post-thumbnail

Annotation

본 글은 2021년 12월 19일 에 기록되었다.

이미 @Override 나 @Overload 등의 라는 키워드는 꽤나 낯익은 녀석들이다. 하지만 이 녀석들이 어떠한 기능을 하고 또 Annotation 들이 어떠한 것들이 있는지에 대해서 알아보기 위해서 따로 공부를 진행하게 되었다.


이론

배경

Java 를 개발한 사람들은 소스코드에 대한 문서를 따로 만들기보다 소스코드와 문서를 하나의 파일로 관리하는 것이 낫다고 생각했다. 소스코드의 주석으로부터 HTML 문서를 생성해내는 프로그램 (javadox.exe) 를 만들어서 사용했다.

정의

Annoatation 은 어떠한 대상에 대한 정보를 담고 그에 따라 추가적인 속성 및 기능을 부여해주는 것이라고 생각하면 편하다.

예를 들면,
A 클래스를 상속 중인 B 클래스의 필드 안에서 특정 메서드를 오버라이드 하려고 한다고 해보자.

이 때,
B 클래스의 메서드의 이름이 A 클래스의 이름과 대소문자가 다를 경우, java 에서는 새로운 메서드를 만든 것으로 간주한다.

하지만,
@Override 라는 Annotation 을 붙이면 이를 찾아내고 이름을 변경하라는 메세지를 받을 수 있다.


종류

Annotation 은 크게 다음과 같이 분류가 가능하다.

  1. Meta Annotation
  2. Non-Meta Annotation

이 중 2번 부터 알아보도록 하겠다.

Non-Meta Annotation

@Override
메서드 앞에만 붙일 수 있는 Annotation 으로
조상의 메서드를 오버라이딩 하는 것이라는 걸 컴파일러에게 알린다.

@Deprecated
새로운 버전의 JDK 가 출시될 때,
새로운 기능이 추가되고 이전의 기능이 개선되기도 한다.
이 경우 기존의 기능을 제거할 경우, 이를 사용하고 있는 많은 부분에서 문제가 발생할 수 있다.

따라서 이런 경우에 @Deprecated 를 통해 사용하지 않을 것을 권고한다는 메세지를 남기는 것이다.

@FunctionalInterface
함수형 인터페이스를 선언할 때, 이 Annotation 을 붙이면 컴파일러가 함수형 인터페이스를 올바르게 선언하였는지 확인해준다.

예를 들면,
함수형 인터페이스는 추상 메서드가 하나만 있어야 한다는 제약을 가지는데 이를 준수하였는지를 보는 것이다.

@SuppressWarnings

이는 컴파일러가 보여주는 경고메세지를 억제하도록 하는 Annotation 이다. 물론 이를 남발하여 경고문을 없애라는 목적이 아니다. 이에 대해서는 Effective Java 4 | Generics 중 아이템 27 | 비검사 경고문을 제거하라를 참고하자.

Essesnsial of Java 에서는 가장 많이 쓰이는 것들 로는 다음과 같은 것들이 있다고 적혀있었다.

  1. @SuppressWarnings("deprecation") | 사용이 자제되는 부분을 사용했음을 경고
  2. @SuppressWarnings("unchecked") | 지네릭스로 타입을 지정하지 않음을 경고
  3. @SuppressWarnings("rawtypes") | 로 타입 사용 자제
  4. @SuppressWarnings("varargs) | 지네릭 타입의 가변인자 사용 자제

둘 이상의 경고문을 무시하려면 @SuppressWarnings({"deprecation", "unchecked", "varags"}); 등으로 적으면 된다.

@SafeVarargs
T... args 와 같이 지네릭스 타입의 가변인자를 받아야 할 경우가 있다면,

이에 대한 안전성을 확인하고 @SafeVarargs 을 사용하도록 하자.
주의할 점은 이름은 SafeVarags 이지만, 실제로는 지네릭스 타입에 대한 unchecked 경고를 억제한다는 점이다.
따라서 @SuppressWarnings("varargs") 를 추가로 작성해주어야 한다.

그렇다면 왜 @SupressWarnings({"varargs","unchecked"}) 라고 쓰지 않을까?
그 이유는 @SuppressWarnings("unchecked") 는 작성된 부분의 경고문만 제거해주지만 @SafeArgs 는 작성된 부분과 사용된 부분의 unchecked 경고문을 제거해주기 때문이다.

Meta Annotation

Meta Annotation 은 Annotation for Annotation 이다.
즉, Annotation 의 적용대상이나 적용기간을 정의한다.

이 부분은 아직은 그리고 앞으로도 필요할지에 대한 확신이 없다.
따라서 책을 읽고 리스트업만하고 넘어가도록 하였다.

@Target

@Target 은 Annotation target 을 정의한다.
이 Annotation 이 가르킬 수 있는 대상은 다음과 같다.

대상 타입의미
ANNOTATION_TPYEAnnotation 어노테이션
CONSTRUCTORConstructor 생성자
FIELDField 필드(멤버변수 혹은 enum 상수)
LOCAL_VARAIBLE지역변수
METHODMethod 메서드
PACKAGEPackage 패키지
PARAMETERParameter 매개변수
TYPEType 타입(클래스, 인터페이스, enum)
TYPE_PARAMETERType Parameter 타입 매개변수(지네릭스, jdk 1.8)
TYPE_USEtype_use 타입이 사용되는 모든 곳 (jdk 1.8)

@Documented
Annotation 에 대한 정보가 javadoc 으로 작성한 문서에 포함되도록 한다.
@Override 와 @SuppressWarnings 를 제외한 모든 전술한 Annotation 에 붙어있다.

@Inherited
Annotation 이 자손 클래스에 상속되도록 한다.

@Repeatable
특정한 Annotation 을 반복사용 가능하게 해준다.
사용 예시는 아래에 있다.

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

@Native
네이티브 메서드 에 참조되는 상수 필드에 붙이는 Annoation 이다.
이는 JVM 이 설치된 OS 의 메서드를 의미하고 이 메서드는 보통 C 언어로 작성되어 있다.
Java 에서는 메서드의 선언부만 작성하고 구현은 하지 않는데, 그래서 추상 메서드처럼 선언부만 있고 몸통이 없다.

public class Object {
   private static native void registerNatives();
   
   static {
      registerNative();
   }
   
   protected native Object clone() throws CloneNotSupportedException;
   
   public final native Class<?> getClass();
   public final native void notify();
   public final native void notifyAll();
   public final native void wait(long timeout) throws InterruptedException;
   public native int hashCode();
   ...
}

모든 클래스의 조상인 Object 클래스는 대부분 Native 메서드이며
이는 Java 로 정의되어 있지만 실제로 호출되는 것은 OS 의 메서드이고
이러한 연결은 JNI(Java Native Interface) 가 하는데 이는 Java 의 영역이나 Essensial of Java 의 범위를 아득히 벗어나는 것 같다.

관련된 포스트 내용을 구글링해서 포스트해두는 것으로 마무리하였다.
JNI 와 NDK 시리즈 - 드럼치는 한동희 님 블로그


정의

Essesnsial of Java 의 715p 부터 720p 까지는
직접 Annotation 을 만들어보고 Marker Annotation 에 대한 내용이 담겨있다.
하지만 Meta Annotation 부터 정의부분까지는 개념적으로도 실제로도 필요한 부분인가에 대한 필요성을 느끼지 못하는 바로 페이지만 적어두고 마무리하였다.

profile
문제없는 기록

0개의 댓글