주석처럼, 프로그래밍 언어에 영향을 미치지 않으며, 유용한 정보를 제공한다.
특정 프로그램에게만 정보를 제공함. (설정 정보..등)
사용 예
@Test // 이 메서드가 테스트 대상임을 테스트 프로그램에게 알린다. (JUnit, 테스트프로그램)
public void method() {
...
}
@Override : 오버라이딩을 올바르게 했는지 컴파일러가 체크
@Deprecated
@SuppressWarnings
@SafeVarargs
@FunctionalInterface
@Native
// 메타 애너테이션(*가 붙음)
@Target*
@Documented*
@Inherited*
@Retention*
@Repeatable*
오버라이딩을 올바르게 했는지 컴파일러가 체크하게 한다.
오버라이딩을 할 때, 메서드 이름을 잘못적는 실수를 하는 경우가 많다.
오버라이딩 할 때는, 선언부 위에 @Override를 붙이자.
애너테이션을 위한 애너테이션
메타 애너테이션은 java.lang.annotation 패키지에 포함
@Target : 에너테이션을 정의할 떄, 적용 대상 지정에 사용
@Retention : 애너테이션이 유지되는 기간을 지정할 때 사용
SOURCE : 소스 파일에만 존재. 클래스 파일에는 존재하지 않음. (컴파일 하기 전까지만 존재. 컴파일 하고나면 사라짐.)
CLASS : 클래스 파일에 존재. 실행 시 사용 불가. 기본값. (ClassLoader 까지 존재)
RUNTIME : 클래스 파일에 존재. 실행 시에 사용 가능. (Runtime 까지 존재)
컴파일러에 의해 사용되는 애너테이션(@Override)의 유지 정책은 SOURCE이다.
@FunctionalInterface의 유지 정책은 RUNTIME이다.
@Documented : javadoc으로 작성한 문서에 포함시키려면, @Documented를 붙인다.
@Inherited : 부모가 가진 애너테이션을 자손 클래스에 상속하고자 할 때, @Inherited를 붙인다.
@Repeatable : 반복해서 붙일 수 있는 애너테이션을 정의할 때 사용
// 적용 대상 지정 (만든 Annotation을 붙일 수 있는 대상을 지정)
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value();
}
// ex1
@Inherited // @SuperAnno는 자손까지 영향이 가게 된다. 자동으로 Annotation도 함께 상속됨.
@interface SuperAnno {}
@SuperAnno
class Parent {}
class Child extends Parent {} // Child에 @SuperAnno라는 애너테이션이 있는 것으로 인식됨.
// ex2 : Repeatable이 붙은 애너테이션은 반복해서 붙일 수 있다.
// @Repeatable인 애너테이션을 하나로 묶을 컨테이너 애너테이션 정의가 필수임.
@Repeatable(ToDos.class)
@interface ToDo {
String value();
}
@interface ToDos { // 여러 개의 ToDo 애너테이션을 담을 컨테이너 애너테이션 ToDos
ToDo[] value(); // Todo[] 배열 요소 선언. 이름은 반드시 value!
}
@ToDo("delete test codes.")
@ToDo("override inherited methods")
class MyClass{
...
}
애너테이션을 직접 만들어서 쓸 수 있다.
애너테이션의 메서드는 추상메서드이다. 애너테이션을 적용할 때 지정한다. (순서 X)
@interface 애너테이션이름 {
타입 요소이름(); // 애너테이션의 요소를 선언한다.
}
@interface DateTime {
String yymmdd();
String hhmmss();
}
@interface TestInfo {
int count();
String testedBy();
String[] testTools(); // 배열
TestType testType(); // enum TestType { FIRST, FINAL }
DateTime testDate(); // 자신이 아닌 다른 애너테이션(@DateTime)을 포함할 수 있다.
}
// 애너테이션 사용. 요소의 값을 타입에 맞게 전부 적어주어야 함.
@TestInfo(
count=3, testedBy="Kim",
testTools={"JUnit", "AutoTester"},
testType=TestType.FIRST,
testDate=@DateTime(yymmdd="160101", hhmmss="235959")
)
public class NewClass { ... }
적용시, 값을 지정하지 않으면 사용될 수 있는 기본값 지정 가능(null 제외)
요소가 하나이고, 이름이 value일 때는, 요소의 이름을 생략할 수 있다.
요소의 타입이 배열인 경우, 괄호{}를 사용한다.
// ex1
@interface TestInfo {
int count() default 1; // 기본값을 1로 지정
}
@TestInfo // @TestInfo(count = 1)과 동일
public class NewClass { ... }
// ex2
@interface TestInfo {
String value();
}
@TestInfo("passed") // @TestInfo(value="passed")와 동일
class NewClass { ... }
// ex3
@interface TestInfo{
String[] testTools();
}
@TestInfo(testTools={"Junit", "AutoTester"})
@TestInfo(testTools="Junit")
@TestInfo(testTools={}) // 값이 없을 때는, 괄호{}가 반드시 필요
java.lang.annotation.Annotation
조상이지만, 상속은 불가능하다. "Interface"이기 때문.
Annotation이 가진 추상 메서드들은 따로 구현하지 않아도 되는데, 이는 컴파일러가 자동으로 해주기 때문이다. 그렇기 때문에, 사용이 가능하다.
요소가 하나도 정의되지 않은 애너테이션
예: @Override, @Test, @Deprecated
요소가 없기 때문에, 아무것도 안적어줘도 됨.
요소의 타입은 기본형, String, enum, 애너테이션, Class만 허용된다.
메서드의 괄호()안에 매개변수를 선언할 수 없다.
예외를 선언할 수 없다.
요소를 타입 매개변수로 정의할 수 없다. (지네릭 타입 불가)