본문 바로가기
IT/Java

[Java Study] 12일차 Annotation

by Dblog 2021. 2. 4.
728x90

학습할 것

  • 애노테이션 정의하는 방법
  • @retention
  • @target
  • @documented
  • 애노테이션 프로세서

 


Annotations 

meta data의 일종, 주석과 비슷한 관계로 미리 약속된 규율이 없었다면 컴파일러는 아무행동도 하지 않는 코드로 생각됩니다.

Annotation은  Java SE 8 부터 활용되고 있으며 활용법은 다음과 같습니다.

  • 컴파일러에게 정보를 주는 역할  : 컴파일러가 에러나 경고를 탐지하는데 사용될 수 있음
  • 컴파일 시간, 배포 시간처리 :  소프트웨어 툴이 annotation으로 코드를 생성하거나 XML을 생성할 수 있음
  • 런타임 처리 : 몇몇 annotation은 런타임 중에 annotation을 검사하고 활용할 수 있습니다.

 

 

애노테이션 정의하는 방법

기본형태

@Entity, @{Name}

@ 지시자는 컴파일러에게 이 타입이 Annotation임을 알립니다. 대표적 예시로 @Override를 예시로 들수 있습니다.

또한 annotation은 이름이 지정되거나 지정되지 않은 element를 포함할 수 있으며 각 element들은 값을 가지고 있어야 합니다(not null).

@Author(
   name = "Benjamin Franklin",
   date = "3/27/2003"
)
class MyClass() { ... }

 

Annotation을 선언할때 지정할 값이 하나라면 따로 name을 지정해서 value를 설정할 필요가 없습니다. 또한 Annotation은 하나에 선언에 여러개의 Annotation을 선언할 수 있습니다. 

같은 Annotation 타입에 여러 값을 선언할때는 Name을 설정해야 합니다.

@SuppressWarnings("unchecked") // → @SuppressWarnings(value = "unchecked")  와 같음
void myMethod() { ... }


//한 선언문에 여러개 선언가능
@Author(name = "Jane Doe")
@EBook
class MyClass { ... }


// 같은 타입에 여러개 값 선언가능 ( java SE8부터 지원)
@Author(name = "Jane Doe")
@Author(name = "John Smith")
class MyClass { ... }

 

이미 선언되어있는 Annotation

java.lang 과 java.lang.annotation 패키지 안에 이미 선언되어있는 Annotation이 존재합니다. 

@Override, @suppressWarings와 같은 Annotation은 이미 Java annotation 패키지 내부에 선언 되어있으며 이 Annotation들은 고유한 타입으로 정의해서 사용할 수 있습니다. 

Annotation이 활용되는곳

  • Class 인스턴스 생성 표현식
    • new @intered MyObject
  • Type 변환
    • myString = (@Nonnull String) Str;
  • implement 절
    • clas UnmodifiableList<T> implements
               @Readonly List<@Readonly T> { ... }
  • Thrown된 예외 선언부
    • void monitor Temperature() throws
                       @Critical TemperatureException { ... }

이런 Annotation을 Type Annotation이라 부르게 됩니다. 


Type Annotation

보다 강력하게 데이터의 결함을 방지합니다. 만약 특정 변수가 null이 되는 것을 방지하고 싶을때 @Nonnull String Str; 을 사용하여 str 변수에 null 값이 들어오는 것을 허용하지 않을수 있습니다. 

Type Annotation을 사용합으로써 더욱 강력하게 데이터 오류를 방지할 수 있습니다.

 

Type Annotation 선언방법

Type Annotation을 선언하는 방법은 java의 interface를 선언하는 것과 비슷합니다. 

마치 Spring에서 @requestmapping에 value와 method를 설정하는 것과 비슷하다고 생각했습니다. 

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;

@Retention(RetentionPolicy.RUNTIME)
@interface AnnotationType{
	String userName() default "DY";
}

public class EnumTest {
	
	@AnnotationType
	public void take1() throws Exception {
	  Method method = EnumTest.class.getMethod("take1", null);
	  AnnotationType annotation = (AnnotationType)method.getAnnotation(AnnotationType.class);
	  System.out.println(annotation.userName());
	}
	
	@AnnotationType(userName = "KIM")
	public void take2() throws Exception {
		  Method method = EnumTest.class.getMethod("take2", null);
		  AnnotationType annotation = (AnnotationType)method.getAnnotation(AnnotationType.class);
		  System.out.println(annotation.userName());
		}

	
	
    public static void main(String[] args) throws Exception {
        EnumTest test = new EnumTest();
        test.take1();
        test.take2();

    }
}

결과

DY
KIM

 

이미 정의 되어있는 Annotation Type

  • @Deprecated
    더 이상 사용하지 않는 요소임을 의미합니다. 만약 이 Annotation이 선언된 요소가 다른곳에서 사용된다면 java 컴파일러는 waring을 생성합니다.
  • @Override
    매서드를 재정의 하였음을 표기합니다.
  • @SuppressWarings
    위 @Deprecated가 선언된 매서드나 클래스를 사용할때 컴파일러가  waring을 발생시키는데 이때 @SupperessWarings가 선언되어 있으면 waring이 발생하지 않음
  • @SafeVargars
    매서드 또는 생성자에 적용될 때 코드가 해당 varargs매게 변수에 대해 잠재적으로 안전하지 않은 작업을 수행하지 않는다는 알림을 발생
  • @FunctionallInterface
    Java SE 8 이상 버전의 functional 인터페이스의 지시자

 

@retention

@retention은 해당 Annotation이 어떻게 저장될지 지정합니다.

  • RetentionPolicy.SOURCE
    표시된 Annotation은 소스레벨에서만 유지되며 컴파일러에서는  무시됩니다.
  • RetentionPolicy.CLASS
    표시된 Annotation은 컴파일 시점에 컴파일러에 의해 유지되지만 JVM에서는 무시 됩니다.
  • RetentionPolicy.RUNTIME
    표시된 Annotation은 JVM에서 유지되므로 런타임 환경에서 사용할 수 있습니다.

 

 

 

@target

Annotation을 사용할 때 종류를 제한하가 위해 사용하는 annotation이라고 합니다

Name Description
ElementType.ANNOTATION_TYPE annotation 타입에 적용 가능
ElementType.CONSTRUCTOR 생성자에 적용가능
ElementType.FIELD 필드, 속성에 적용가능
ElementType.LOCAL_VARIABLE 로컬 변수(지역변수)에 적용가능
ElementType.METHOD  메서드 레벨에서 적용가능
ElementType.PACKAGE  패키지 선언에 적용가능
ElementType.PARAMETER  메서드의 매개변수에 적용가능
ElementType.TYPE can be applied to any element of a class. 클래스 모든 요소에 적용가능

 

 

@documented

Javadoc tool을 이용해 문서화 해야하는 것을 의미합니다.

javadoc은 우리가 IDE에서 class, interface 혹은 method에 마우스를 올려놨을때 등장하는 팝업을 만들수 있는 도구 입니다. 

https://ko.wikipedia.org/wiki

 

애노테이션 프로세서

소스레벨에서 컴파일러가 소스를 컴파일 하는 과정에서 활용됩니다.

기존 코드에 새로운 코드를 생성하거나, 변경하는 작업을 가능하게 합니다. 가장 좋은 예시는 Lombok이며

@getter @setter,가 가장 좋은예시 입니다. @getter @setter    annotation이 사용되면 자동으로 get, set 메서드를 생성하고 사용할 수 있게 바꿔주지만 소스레벨에서는 메서드 들이 보이지는 않습니다.

컴파일할때 자동 생성됩니다.

 

reference

- https://docs.oracle.com/javase/tutorial/java/annotations/index.html

728x90

댓글