// 애노테이션 사용
@Override
void mySuperMethod() { ... }
// 애노테이션의 요소
@Author(
name = "Benjamin Franklin",
date = "3/27/2003"
)
class MyClass { ... }
// 요소 이름 생략 가능
@SuppressWarnings("unchecked")
void myMethod() { ... }
// 요소가 없으면 괄호 생략 가능
@Author(name = "Jane Doe")
@EBook
class MyClass { ... }
// 반복주석 - 자바8부터 가능
@Author(name = "Jane Doe")
@Author(name = "John Smith")
class MyClass { ... }
new @Interned MyObject();
myString = (@NonNull String) str;
implements
사용시class UnmodifiableList<T> implements
@Readonly List<@Readonly T> { ... }
throws
를 사용해 예외 선언시void monitorTemperature() throws
@Critical TemperatureException { ... }
자바에서 기본적으로 제공하는 애노테이션
@Override
@Deprecated
@SuppressWarnings
@SuppressWarnings(”unchecked”)
@SuppressWarnings(”deprecation”, ”unchecked”, ”varargs”)
@SafeVarargs
제네릭 타입의 가변인자에 사용한다.(JDK 1.7 부터)
static 이나 final 이 붙은 메서드와 생성자에만 붙일 수 있다.
메서드에 선언된 가변인자의 타입이 non-reifiable 타입일 경우
해당 메서드를 선언하는 부분과 호출하는 부분에서 unchecked 경고가 발생
- reifiable : 컴파일 후에도 제거되지 않는 타입
- non-reifiable : 컴파일 후 제거되는 타입 : 제네릭, 경계타입
- https://cla9.tistory.com/52
코드에 문제가 없다면 이 경고를 억제하기 위해 @SafeVarargs
를 사용해야한다.
ArrayList<T>
를 생성하는것이 위험하다고 경고@SafeVarargs
를 사용해 타입안정성이 있다고 컴파일러에게 알려 경고 억제참고
@SafeVarargs
와 @SuppressWarnings
@SafeVarargs
사용시 메서드를 호출하는 곳에서 발생하는 경고도 억제됨@SuppressWarnings(”unchecked”)
를 통해 억제하고싶다면, 메서드 선언부와 호출부 모두 애노테이션을 사용해야한다.@SafeVarargs
사용시 @SuppressWarnings(”varargs”)
를 함께 사용@SafeVarargs
를 통해 unchecked 경고는 억제 가능한 반면에@SuppressWarnings(”varargs”)
를 함께 사용해 varargs 경고를 억제한다.@FunctionalInterface
@Native
@Target
@Target({FIELD, TYPE, TYPE_USE})
public @interface MyAnnotation{ }
{}
를 사용java.lang.annotation.ElementType
열거형에 정의 - TYPE_PARAMETER 와 TYPE_USE 는 JDK 1.8 부터 가능
- FIELD 는 기본형에, TYPE_USE 는 참조형에 사용된다.
@Retention
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override { }
애노테이션이 유지되는 기간을 지정하는데 사용
SORCE
@Override
나 @SuppressWarnings
처럼 컴파일러가 사용하는 애노테이션은 유지정책이 SOURCE 이다.CLASS
RUNTIME
@FunctionalInterface
의 경우 컴파일러가 체크해주는 애노테이션이지만, 실행시에도 사용되므로 유지정책이 RUNTIME
으로 되어있다.리플렉션이란 객체를 통해 클래스의 정보를 분석해 내는 프로그램 기법을 말한다.
리플렉션은 구체적인 클래스 타입을 알지 못하더라도 그 클래스의 메서드, 타입, 변수들에 접근할 수 있도록 해주는 자바 API
컴파일 타임이 아닌 런타임에 동적으로 클래스의 정보를 추출할 수 있다.
@Documented
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FunctionalInterface { }
@Override
와 @SuppressWarnings
를 제외한 모두는 해당 애노테이션이 붙어있다.@Inherited
@Inherited
@interface SupperAnnotation{}
@SupperAnnotation
class Parent{}
class Child extend Parent{}
@Repeatable
// 애노테이션을 묶을 애노테이션이 필요
@interface ToDos{
ToDo[] value();
}
@Repeatable(ToDos.class)
@interface ToDo{
String value();
}
@ToDo("delete test codes.")
@ToDo("override inherited methods")
class MyClass{...}
사용자가 직접 정의하여 사용하는 어노테이션
프레임워크나 API 등을 만들어 사용할 때 주로 사용
직접 애노테이션 타입 정의
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface TestInfo{
int count() default 1;
String testedBy();
String[] testTools() default "JUnit";
TestType testType() default TestType.FIRST; // enum TestType
DateTime testDate(); // 다른 애노테이션을 포함(@DateTime)
}
@interface 애너테이션이름 {
타입 요소이름();
}
@Override
에서 @Override
는 애노테이션이고, Override 는 애노테이션의 타입
이다.{}
를 사용해 여러 값을 지정할 수 있다.equals()
hashCode()
toString()
// 클래스에 있는 애노테이션 정보를 확인하기 위한 코드
Class<MyClass> myClass = MyClass.class;
Annotation[] annoArr = myClass.getAnnotations();
if (annoArr.length == 0) {
System.out.println("empty !!");
} else {
for (Annotation annotation : annoArr) {
System.out.println(annotation);
System.out.println("annotation.toString() = " + annotation.toString());
System.out.println("annotation.hashCode() = " + annotation.hashCode());
System.out.println("annotation.equals(annotation) = " + annotation.equals(annotation));;
System.out.println("annotation.annotationType() = " + annotation.annotationType());
}
}
@Retention()
조건에 따라 애노테이션 정보를 가져오지 못할 수 있다.일종의 자바 컴파일러 플로그인으로
컴파일 단계에서 애노테이션들을 스캐닝하고 프로세싱하는 javac 에 속한 빌드 툴
- 소스 또는 리소스 파일 세트 생성
- 기존 소스 코드를 변경
- 기존 소스 코드 분석 및 진단 메세지 생성
특정 애노테이션이 동작하기 위해 애노테이션 프로세서를 만들어 등록할 수 있다.
모든 애노테이션 프로세서들은 AbstractProcessor 를 상속받아야한다.
애노테이션 프로세서 사용 예 (롬복이란)