1. 애너테이션(Annotation)이란?
- 주석(comment)처럼 프로그래밍 언어에 영향을 미치지 않으면서, 다른 프로그램에게 유용한 정보 제공
2. 표준 애너테이션
- 자바에서 기본적으로 제공하는 애너테이션
- 주로 컴파일러에게 유용한 정보 제공
@Override | 컴파일러에게 오버라이딩하는 메서드라는 것을 알림 |
@Deprecated | 앞으로 사용하지 않을 것을 권장함 |
@SuppressWarnings | 컴파일러의 특정 경고메시지가 나타나지 않게 해줌 |
@SafeVarargs | 지네릭스 타입의 가변인자에 사용 (JDK1.7) |
@FunctionalInterface | 함수형 인터페이스라는 것을 알림 (JDK1.8) |
@Native | native메서드에서 참조되는 상수 앞에 붙임(JDK1.8) |
① @Override
- 메서드 앞에만 붙임
- 조상의 메서드를 오버라이딩한 것이라는 걸 컴파일러에게 알려줌
- 같은 이름의 메서드가 조상에 있는지 확인하고, 없으면 에러메시지 출력
- 입력 실수를 미연에 방지하므로 필수는 아니지만 명시해주는 것이 좋음
② @Deprecated
- 더 이상 사용되지 않는 필드나 메서드에 붙임
- 다른 것으로 대체되었으니 더 이상 사용하지 않을 것을 권한다는 의미
③ @FunctionalInterface
- 함수형 인터페이스(functional interface)를 선언할 때 붙임
- 함수형 인터페이스를 올바르게 선언했는지 확인하고, 잘못된 경우 에러를 발생시킴
④ @SuppressWarnings
- 컴파일러의 경고메시지를 보이지 않게 억제시킴
- 억제하려는 경고 메시지를 괄호 안에 문자열로 지정
@SuppressWarnings("unchecked") // 지네릭스 관련 경고 억제
ArrayList list = new ArrayList(); // 지네릭 타입을 지정하지 않음
list.add(obj); // 경고 발생
// 둘 이상의 경고 동시 억제 가능
@SuppressWarnings({"deprecation", "unchecked", "varargs"})
⑤ @SafeVarargs
- 메서드에 선언된 가변인자의 타입이 non-reifiable타입일 경우, unchecked 경고 발생
- 이를 억제하기 위해 사용
가변인자(Varargs, variable arguments)
- 매개변수의 개수를 동적으로 지정해줄 수 있음
- JDK1.5부터 사용
- '타입...변수명'의 형태로 사용
- 내부적으로 배열을 생성해서 사용함
- 빈 인자값, 같은 타입의 배열 인자값 가능
- 매개변수가 여러개라면 가변인자는 항상 마지막에 선언해야 함
non-reifiable 타입 : 컴파일 후에 제거되어 런타임 시에는 타입 정보를 알 수 없음 (지네릭 타입)
reifiable 타입 : 컴파일 후에도 제거되지 않아 런타임 시에 타입 정보를 알 수 있음
public static <T> List<T> asList(T... a) {
return new ArrayList<T>(a); // ArrayList(E[] array)를 호출, 경고 발생
}
-> 가변인자인 동시에 지네릭 타입
-> 컴파일러가 체크하여 타입 T가 아닌 다른 타입이 들어가지 못하게 함으로 안전함
-> @SafeVarargs로 이 메서드의 가변인자는 타입 안전성이 있다고 컴파일러에게 알림
-> @SafeVarargs로 unchecked 경고는 억제 가능하지만 varargs 경고는 억제 불가능
-> @SupressWarnings("varargs")를 같이 붙여 해결함
@SafeVarargs // 'unchecked' 경고 억제
@SuppressWarning("varargs") // 'varargs' 경고 억제
public static <T> List<T> asList(T... a) {
return new ArrayList<T>(a); // ArrayList(E[] array)를 호출, 경고 발생
}
3. 메타 애너테이션
- 애너테이션을 위한 애너테이션
- 애너테이션을 정의할 때 애너테이션의 적용대상(target)이나 유지기간(retention) 등을 지정하는데 사용
@Target | 애너테이션이 적용가능한 대상을 지정하는데 사용 |
@Documented | 애너테이션 정보가 javadoc으로 작성된 문서에 포함되게 함 |
@Inherited | 애너테이션이 자손 클래스에 상속되게 함 |
@Retention | 애너테이션이 유지되는 범위를 지정하는데 사용 |
@Repeatable | 애너테이션을 반복해서 적용할 수 있게 함(JDK1.8) |
① @Target
- 애너테이션이 적용가능한 대상 지정
- 여러 개의 값을 지정할 때는 배열처럼 { } 사용
- 지정할 수 있는 애너테이션 적용대상의 종류 : ANNOTATION_TYPE, CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE, TYPE_PARAMETER, TYPE_USE
② @Retention
- 애너테이션이 유지(retention)되는 기간을 지정
- RetentionPolicy.SOURCE : 소스 파일에만 존재, 클래스 파일에는 존재X
- RetentionPolicy.CLASS : 클래스 파일에 존재, 실행시에 사용불가, 기본값
- RetentionPolicy.RUNTIME : 클래스 파일에 존재, 실행시에 사용가능
③ @Documented
- 애너테이션에 대한 정보가 javadoc으로 작성한 문서에 포함되도록 함
- @Override, @SuppressWarnings을 제외하고 모두 붙어있음
④ @Inherited
- 애너테이션이 자손 클래스에 상속되도록 함
- 애너테이션을 조상 클래스에 붙이면, 자손 클래스도 이 애너테이션이 붙은 것과 같이 인식됨
⑤ @Repeatable
- 보통 하나의 대상에 한 종류의 애너테이션이 붙지만, @Repeatable을 붙이면 여러 번 붙일 수 있음
⑥ @Native
- 네이티브 메서드(native method)에 의해 참조되는 '상수 필드(constant field)'에 붙이는 애너테이션
4. 애너테이션 타입 정의하기
@interface 애너테이션이름 {
타입 요소이름();
...
}
1) 애너테이션의 요소(element)
- 애너테이션 내에 선언된 메서드
- 추상 메서드의 형태(반환값이 있고 매개변수는 없음)
- 상속을 통해 구현하지 않아도 됨
- 단, 애너테이션 적용 시 요소들의 값을 빠짐없이 지정해줘야 함 (순서는 상관 X)
- 기본값을 가질 수 있고, 값을 지정하지 않으면 기본값이 사용됨
@interface TestInfo {
int count() default 1;
}
@TestInfo // @TestInfo(count=1)와 동일
public class NewClass { ... }
2) java.lang.annotation.Annotation
- 모든 애너테이션의 조상
- 애너테이션은 상속이 허용되지 않으므로 명시적으로 Annotation을 조상으로 지정할 수 없음
- Annotation은 애너테이션이 아닌 일반 인터페이스로 정의되어 있음
- 따라서 모든 애너테이션 객체는 equals(), hashCode(), toString()과 같은 메서드를 호출할 수 있음
3) 마커 애너테이션(Marker Annotation)
- 요소가 하나도 정의되지 않은 애너테이션
- ex) Serializable, Cloneable
4) 애너테이션 요소의 규칙
- 요소의 타입은 기본형, String, enum, 애너테이션, Class만 허용
- ()안에 매개변수를 선언할 수 없음
- 예외를 선언할 수 없음
- 요소를 타입 매개변수로 정의할 수 없음
@interface AnnoTest {
int id = 100; // O, 상수 선언
String major(int i, int j); // X, 매개변수 선언 불가
String minor() throws Exception; // X, 예외 선언 불가
ArrayList<T> list(); // X, 요소의 타입에 타입 매개변수 불가
}
참고 - Java의 정석 3rd Edition (저자 : 남궁성, 출판 : 도우출판)
'공부 > Java' 카테고리의 다른 글
[Java-14] 람다식(Lambda expression) (0) | 2021.07.06 |
---|---|
[Java-13] 쓰레드(Thread) (0) | 2021.07.06 |
[Java-12] 열거형(Enums) (0) | 2021.07.02 |
[Java-12] 지네릭스(Generics) (0) | 2021.07.02 |
[Java] BufferedReader와 BufferedWriter (0) | 2021.06.13 |