[Java] 어노테이션(Annotation)
본문 바로가기
Java

[Java] 어노테이션(Annotation)

by IYK2h 2023. 7. 4.
728x90

어노테이션(Annotation)

목차

어노테이션을 정의하는 방법

public @interface MyAnnotation {
}

어노테이션도 enum과 마찬가지로 1.5에 등장했다.

생성된 어노테이션의 부모는 java/lang/annotation/Annotation이다.

// 바이트 코드
public abstract @interface study/MyAnnotation
                             implements java/lang/annotation/Annotation {
    // compiled from: MyAnnotation.java
}

어노테이션은 리플렉션을 사용한다는 것을 알 수 있다.

Annotation annotation = new Annotation() {
     @Override
     public Class<? extends Annotation> annotationType() {
        return null;
};

어노테이션 필드

어노테이션에 필드 같은 요소들을 정의할 수 있습니다.(사실은 추상 메서드)

어노테이션 요소의 규칙

  • 요소의 타입은 기본형, String, enum, 어노테이션, Class만 가질 수 있습니다.
  • 배열을 선언할 수 있습니다. String[] arr();
  • default값을 지정할 수 있습니다. int number() default 100;
  • 예외를 선언할 수 없습니다.
  • 메서드 선언은 throws 절을 가질 수 없습니다.
  • 요소를 타입 매개변수로 정의할 수 없습니다.
  • 어노테이션 요소의 타입 선언은 제네릭일 수 없습니다.
  • extends 절을 가질 수 없습니다. (암묵적으로 java.lang.annotation.Annotation을 상속합니다.)
  • 메서드는 매개변수(Parameter)를 가질 수 없습니다.
  • 메서드는 타입 매개변수(Type Parameter)를 가질 수 없습니다.

자바 8에서는 다음과 같은 곳에도 어노테이션을 사용할 수 있습니다.

  • 클래스 인스턴스를 생성할 때
    • new @Interned MyObject();
  • 타입 캐스트
    • myString = (@NonNull String) str;
  • 인터페이스 구현(implements)
    • class UnmodifiableList<T> implements @Readonly List<@Readonly T> { . . . }
  • 예외를 throws 할 때
    • void monitorTemperature() throws @Critical TemperatureException { . . . }

어노테이션의 종류

어노테이션은 총 2가지로 나뉜다.

Built-in Annotation : 자바에서 기본적으로 제공하는 어노테이션

Meta Annotation : 커스텀 어노테이션을 만들 수 있게 제공된 어노테이션.

실제로는 Meta Annotation을 통해 만든 커스텀 어노테이션까지 세 가지로 나뉜다

빌트인 (built-in) 어노테이션(기본적으로 제공)

annotationdescription

@Override 오버라이딩 된 메소드에 사용
@Deprecated 사용을 권장하지 않는 메소드에 사용 (IDE에 취소선으로 표시됨)
@SuppressWarnings 컴파일 경고를 무시하도록 할 때 사용
@SafeVarargs 가변인자 parameter 사용시 경고를 무시할 때 사용 (jdk 1.7 이상)
@FunctionalInterface 함수형 인터페이스임을 명시할 때 사용 (jdk 1.8 이상) '@Override' 처럼 컴파일러가 체크해주는 애너테이션이지만, 실행 시에도 사용되므로 유지 정책이 "RUNTIME"으로 되어 있다.

메타 어노테이션

메타 어노테이션을 이용해 커스텀 어노테이션을 만들 수 있다. (어노테이션을 정의하는 데 사용하는 어노테이션)

annotationdescription

@Retention 어노테이션의 범위라고 할수 있다. 어떤 시점까지 어노테이션이 영향을 미치는지 결정한다.
@Target 어노테이션이 적용할 위치를 결정한다.
@Documented 문서에도 어노테이션의 정보가 표현된다.
@Inherited 이 어노테이션을 선언하면 부모클래스에서 어노테이션을 상속받을 수 있다.
@Repeatable 반복적으로 어노테이션을 선언할 수 있게 한다.

@retention

어노테이션이 유지(retention)되는 기간을 지정하는 데 사용됩니다. 즉, 어노테이션 정보를 언제까지 유지할 것인지 정하는 것이다. 소스파일, 클래스파일, 메모리

유지 정책의미

SOURCE 소스 파일에만 존재. 클래스 파일에는 존재하지 않음
CLASS(디폴트 값) 클래스 파일에 존재. 실행시에 사용 불가. Default 값
RUNTIME 클래스 파일에 존재. 실행시에 사용가능.

 

@target

적용할 위치를 결정한다.

@Target(ElementType.TYPE) 클래스의 어떤 요소에나 적용 가능, 기본값

@Target(ElementType.FIELD) 클래스의 특정 필드
@Target(ElementType.METHOD) 클래스의 메서드
@Target(ElementType.PARAMETER) 메서드의 피라미터
@Target(ElementType.CONSTRUCTOR) 생성자
@Target(ElementType.LOCAL_VARIABLE) 로컬 변수
@Target(ElementType.ANNOTATION_TYPE) 어노테이션 타입

@documented

documened 어노테이션을 사용한 뒤 내가 java doc 문서 만들면 @documened가 붙은 어노테이션이 문서에 표기된다

@Inherited

어노테이션이 자손 클래스에 상속되도록 합니다. '@Inherited'가 붙은 어노테이션을 조상클래스에 붙이면, 자손 클래스도 이 어노테이션이 붙은 것과 같이 인식됩니다.

어노테이션 프로세서

인프런 - 더 자바, 코드를 조작하는 다양한 방법

어노테이션 프로세서는 자바 컴파일러 플러그인의 일종으로 어노테이션에 대한 코드베이스를 검사, 수정, 생성하는 역할을 가지는 플러그인을 말합니다. 컴파일 타임에 어노테이션 정보를 참고하여 코드를 분석하고 새로운 소스코드를 생성하거나, 기존의 코드 변경 등의 작업을 할 수 있는 기능입니다. 하지만, 코드 변경은 추천하지 않습니다.

대표적인 예제

  • 롬복(Lombok)
    • @Getter, @Setter, @Builder
  • AutoService : java.util.ServiceLoader용 파일 생성 유틸리티
    • 리소스 파일을 만들어줍니다.
    • META-INF 밑의 service 밑에 ServiceLoader용 레지스트리 파일을 만들어줍니다.
  • @Override
    • 컴파일러가 오버라이딩하는 메서드가 잘못된 대상임을 체크해 주는 것도 애노테이션 프로세서
  • Dagger2 : 컴파일 타임 DI 제공 -> 런타임 비용이 없어집니다.
  • 안드로이드 라이브러리
    • ButterKnife : @BindView (뷰 아이디와 애노테이션 붙인 필드 바인딩)
    • DeepLinkDispatcher : 특정 URI 링크를 Activity로 연결할 때 사용

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

  • 컴파일 타임에 동작하기 때문에 런타임 비용이 없습니다.

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

  • 기존의 코드를 고치는 방법으로는 현재로서는 public 한 api가 없습니다.

어노테이션 프로세서 동작구조

Create Annotation Classes.

Create Annotation Parser classes.

Add Annotations in your project.

Compile, and Annotation Parsers will handle the Annotations.

Auto-generated classes will added in build folder.

Abstract Annotation

Annotation Processor를 만들기 위해서는 Abstract Annotation을 상속받는다.

Lombok @Getter, @Setter 직접 만들어 보자

728x90

'Java' 카테고리의 다른 글

[Java] 제네릭(Generic)  (0) 2023.08.07
[Java] I/O  (0) 2023.07.22
[Java] 리플렉션(Reflection)  (0) 2023.06.30
[Java] 바이트코드 조작  (0) 2023.06.23
[Java] 코드 커버리지  (0) 2023.06.21

댓글