자바를 개발하면서 소스코드에 대한 문서를 따로 만들기보다 소스코드와 문서를 하나의 파일에서 관리하는 방법을 선택했습니다.
소스코드의 주석/** ... */에 정보를 저장하고, 그 주석으로부터 HTML 문서를 생성해내는 javadoc 을 사용했습니다.
주석에 포함된 @가 붙은 태그들을 javadoc 이 읽어서 문서를 작성하는데사용했습니다.
이러한 기능을 응용한 것이 Annotation 입니다.
Annotation 은 주석처럼 코드에는 영향이 없으면서, javadoc 처럼 다른 프로그램에게 정보를 제공하는 기능을 합니다.
자바에서
기본적으로제공하는annotation입니다.
주로컴파일러에게 정보를 제공하는 역할을 합니다.
Standard Annotation 설명 @Override 컴파일러에게 오버라이딩 메서드라는 것을 알림 @Deprecated 대상은 앞으로 사용하지 않는 것을 권장 함 @SuppressWarnings 컴파일러의 특정 경고 메시지를 발생하지 않도록 함 @SafeVarargs 제네릭 타입의 가변인자에 사용 @FunctionalInterface 함수형 인터페이스라는 것을 알림 @Native native 메서드에서 참조되는 상수에 사용
@Override를 사용하면 오버라이딩 할 때 발생할 수 있는오타등의 문제를방지할 수 있습니다. 조상 클래스에 같은 시그니처의 메서드가 없으면 컴파일러 에러가 발생합니다.- java 는
backward compativility를 매우 중요하게 생각합니다. 따라서@Deprecated가 붙은 소스코드를 여러 곳에서 확인할 수 있는데,사용하지 않는 것이 좋습니다. 사용하게 되면 컴파일러경고 메시지가 출력됩니다.@FunctionalInterface를 사용하면 함수형 인터페이스를 올바르게 선언했는지 확인할 수 있습니다. 단 하나의 추상메서드를 가진 인터페이스가 아닌 경우 컴파일러 에러가 발생합니다.@SuppressWarnings를 사용하면컴파일러 경고 메시지를억제합니다. 단순히 보기 싫은 경고 메시지를 위해 사용하는 것이 아닌, 경고에 대한인지와조치를 취한 뒤 사용해서,새로운 문제가 발생 했을 때 알 수 있도록 활용하는 것이 좋습니다.
Meta annotation은 다른annotation을정의할 때 사용하는 annotation 입니다.
Meta Annotation 설명 @Target 이 애너테이션이 적용될 수 있는 대상을 지정 @Document 애너테이션 정보가 javadoc 문서에 포함되도록 함 @Inherited 애너테이션이 자손 클래스로 상속되도록 함 @Retention 애너테이션이 유지되는 범위를 지정 @Repeatable 애너테이션을 반복해서 적용할 수 있도록 함
@Target으로 적용대상을 지정해주지 않으면 기본적으로 모든 대상에 적용 가능합니다.
- 애너테이션을 정의할 때는 인터페이스와 유사하게 정의하면 됩니다.
- 상수는 정의할 수 있지만, default 메서드는 정의할 수 없습니다.
- 반환값이 있고 매개변수가 없는 추상메서드 형태의 맴버들을
element(요소)라고 합니다.- 요소의
default값을 정해줄 수 있습니다.
요소가 없는annotation 을marker annotaion이라고 합니다.- @Override 는 marker annotation 입니다.
@Target(ElementType.METHOD) @Retention(RetentionPolicy.SOURCE) public @interface Override { }
import java.lang.annotation.Annotation;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
public class AnnotationTest {
public static void main(String[] args) {
ParentClass parent = new ParentClass();
@SuppressWarnings({"unchecked"})
Class<ParentClass> parentClass = (Class<ParentClass>) parent.getClass();
Annotation[] annotations = parentClass.getAnnotations();
MyAnnotation myAnnotation = (MyAnnotation) annotations[0];
System.out.println(myAnnotation.count());
ChildClass child = new ChildClass();
Class<ChildClass> childClass = (Class<ChildClass>) child.getClass(); // unchecked warning
MyAnnotation annotation = childClass.getAnnotation(MyAnnotation.class);
System.out.println(annotation.testBy());
}
}
@MyAnnotation(testType = TestType.FIRST, testDate = @DateTime(yymmdd = "250101", hhmmss = "246060"))
@ValueAnnotation({3, 4, 5})
class ParentClass {
@DateTime(yymmdd = "123456", hhmmss = "123456")
public int i = 10;
}
class ChildClass extends ParentClass {}
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@interface MyAnnotation {
int MAX = 999;
int count() default 0;
String testBy() default "user";
String[] testTools() default {};
TestType testType();
DateTime testDate();
}
enum TestType { FIRST, FINAL }
@Retention(RetentionPolicy.RUNTIME)
@interface DateTime {
String yymmdd();
String hhmmss();
}
@interface ValueAnnotation {
int[] value() default { 1, 2 };
}