프로그램을 작성하다보면 종종 @이라는 문자를 본다.
어노테이션이라고 부르는건 알겠는데 정확한 사용 방법과 어떻게 수정하는지 등에 대해서 명확하게 알지 못했다.
어노테이션의 용도
1. 컴파일러에게 코드 작성 문법 에러를 체크하도록 정보를 제공한다.
우리가 코드를 작성하고 나서 이 코드가 제대로 잘 작성이 되었는지, 잘못 작성이 되었는지 컴파일러에게 검사할 수 있도록 정보를 제공해주는 역할이다.
대표적인 예로 @Override 이다. 이 어노테이션은 컴파일러에게 내가 지금 작성하고 있는 코드가 부모 클래스에 있는 메서드인지 검사해보라는 의미이다.
2. 소프트웨어 개발 툴이 빌드나 배치시 코드를 자동으로 생성할 수 있도록 정보를 제공한다.
나중에 자바 프로그램을 개발하고난 이후 jar나 war형식으로 압축을 해야할 경우가 생긴다. 이런 경우 어떤 파일 형식으로 압축을 하라고 지시를 할 경우에도 사용하게 된다.
3. 실행시(런타임시) 특정 기능을 실행하도록 정보를 제공한다.
예를들어 어떤 객체를 만들었는데 이 객체는 다른 객체와는 달리 특별한 역할을 수행해야 하는 객체를 만들어야 한다고 할 때, 이 객체에게 어노테이션을 기술해주면 이 어노테이션에 있는 데이터를 보고 특별한 역할을 수행할 수 있게 된다. 대표적으로 서블릿을 만들거나 컨트롤러를 만들 경우에 사용된다.
어노테이션 파일 생성 방법
아래와 같이 소스를 작성해서 만들 수 있게 되는데, 이 때 AnnotationName이라는 이름과 동일한 이름의 파일을 생성해야 한다.
public @interface AnnatationName {
}
[파일명 : AnnotationName.java]
어노테이션의 엘리먼트(element) 멤버
- 어노테이션은 하나 이상의 엘리먼트 멤버를 가질 수 있다.
- 엘리먼트는 외부의 값을 입력받을 수 있는 역할을 한다.
- 여기서 외부의 값이란 개발자가 입력한 값을 의미한다.
- 엘리먼트 선언
public @interface AnnatationName {
타입 elementName() [default 값]; // element 선언
}
element의 타입으로는 primitive type과 reference type 둘다 올 수 있다.
(primitive type : 기본 타입으로 int, byte 등을 의미한다. reference type은 참조타입으로 String, Integer 등을 의미한다.)
[default 값] 부분은 선택사항으로, 값을 주지 않았을 경우에 가지는 기본값을 설정하지 않을 거라면 생략 가능하다.
하지만 기본값을 주지 않았을 경우에는 어노테이션이 적용되는 부분에서 반드시 element값을 전달 해주어야 한다.
다음 예시를 보자.
public @interface AnnatationName {
String elementName1();
int elementName2() default 5;
}
AnnatationName이라는 어노테이션은 elementName1, elementName2 라는 두 개의 element를 가진다.
그리고 elementName1은 기본값이 없어서 선언시에 반드시 전달해주어야 하고
elemebtName2는 기본값을 5로 가지기 때문에 선언시 값을 전달해주지 않으면 5라는 기본값을 가지게 된다.
아래는 그 적용 예시이다.
@AnnotationName(elementName1="값", elementName2=10)
또는
@AnnotationName(elemebtName1="값")
기본 엘리먼트 value
어노테이션을 선언할 때 value라는 element를 선언할 수 있는데, 이 element는 조금 다르게 동작한다.
public @interface AnnotationName {
String value(); // 기본 element
int elementName() default 5;
}
이 value라는 elemnt의 특징은, 값을 전달할 때 element의 이름을 생략할 수 있다는 점이다.
즉, 다음과 같이 선언해서 사용할 수 있다.
@AnnotationName("값")
하지만 어노테이션에 두 개 이상의 속성에 값을 넣을 때는 다음과 같이 value라는 이름을 꼭 명시 해주어야 한다.
@AnnotationName(value="값", elementName=10)
어노테이션 적용 대상
- 코드 상에서 어노테이션을 적용할 수 있는 대상으로 어노테이션을 만들 때 지정할 수 있다.
- java.lang.annotation.ElementType 열거 상수로 정의되어 있음
ElementType 열거 상수 |
적용 대상 |
Type | 클래스, 인터페이스, 열거 타입 |
ANNOTATION_TYPE | 어노테이션 |
FIELD | 필드 |
CONSTRUCTOR | 생성자 |
METHOD | 메서드 |
LOCAL_VARIABLE | 로컬 변수 |
PACKAGE | 패키지 |
어노테이션 적용 대상 지정 방법
- @Target 어노테이션으로 적용 대상 지정
- @Target의 기본 엘리먼크인 value의 타입은 ElementType 배열
@Target()
public @interface AnnotationName {
}
위 소스의 의미는, AnnotationName이라는 어노테이션은 TYPE, FIELD, METHOD에 적용할 수 있음을 뜻한다.
위에서 작성한 소스가 적용되는 예시는 다음과 같다.
@AnnotationName
public class ClassName {
@AnnotationName
private String fieldName;
// @AnnotationName
// 생성자에는 적용할 수 있다고 명시하지 않았기 때문에 생성자에는 적용할 수 없다.
public className() { }
@AnnotationName
public void methodName() { }
}
어노테이션 유지 정책
- 어노테이션 적용 코드가 유지되는 시점을 지정하는 것이다. 즉, 해당 어노테이션에 대한 정보를 어느 순간까지 얻어올 수 있는지를 지정하는 것이다.
- java.lang.annotation.RetentionPolicy 열거 상수로 정의되어 있다.
RetentionPolicy 열거 상수 |
설명 |
SOURCE | 소스상에서만 어노테이션 정보를 유지한다. 소스 코드를 분석할 떄만 의미가 있으며, 바이트 코드 파일에는 정보가 남지 않는다. 바이트 코드에서는 유지되지 않는 정책. |
CLASS | 바이트 코드 파일까지 어노테이션 정보를 유지한다. 하지만 리플렉션을 이용해서 어노테이션 정보를 얻을 수는 없다. 바이트 코드를 만들 때 까지는 유지를 하는 정책. |
RUNTIME | 바이트 코드 파일까지 어노테이션 정보를 유지하면서 리플렉션을 이용해서 런타임에 어노테이션 정보를 얻을 수 있다. 실제 런타임 시기에도 유지하는 정책으로 보통 이 정책을 많이 사용한다. |
{
리플렉션 (Reflection) : 런타임 클래스의 메타 정보를 얻는 기능
- 클래스가 가지고 있는 필드, 생성자, 메소드, 어노테이션의 정보를 얻을 수 있다.
- 런타임시에 어노테이션 정보를 얻으려면 유지 정책을 runtime으로 설정해야 한다.
}
유지 정책 지정 방법
- @Retention 어노테이션으로 유지 정책을 지정한다.
- @Retention의 기본 엘리먼트인 value의 타입은 RetentionPolicy
@Target()
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationName {
}
내용 참고 ] 이것이 자바다(신용권의 Java 프로그래밍 정복). 한빛미디어 출반사. 신용권 저.
'프로그래밍 언어 > Java' 카테고리의 다른 글
javaFX MDI(Multi Document Interface) 답답해서 정리 (0) | 2017.06.05 |
---|---|
자바 @어노테이션 정리 2편 (0) | 2017.06.03 |
자바 함수형 인터페이스와 람다식 2편 : 생략 문법과 제약사항 (0) | 2017.05.31 |
자바 함수형 인터페이스와 람다식 1편 : 기본 개념과 사용법 (0) | 2017.05.30 |
java 접근 제한자와 가시성, private을 통한 encapsulation과 information hiding (0) | 2017.05.25 |