12.3.1 애너테이션이란?
- 프로그램의 소스코드 안에서 다른 프로그램을 위한 정보를 미리 약속된 형식으로 포함시킨 것
- 프로그램 자체에는 아무런 영향일 끼치지 않음
@Test // 이 메서드가 테스트 대상임을 테스트 프로그램에게 알림 public void method(){...}
- 해당 프로그램에 미리 정의된 종류와 형식으로 작성해야 의미가 있음
- JDK에서 제공하는 표준 애너테이션은 주로 컴파일러를 위한 것임
12.3.2 표준 애너테이션 종류
- @Override
- 메서드 앞에만 붙일 수 있음
- 조상의 메서드를 오버라이딩하는 것이라는걸 컴파일러에게 알리는 역할을 함
@Override void parentmethod()
- @Deprecated
- 더 이상 사용하지 않는 것을 권장한다는 의미임
@Deprecated int oldField
- @SuppressWarnings
- 경고 메시지가 나타나지 않게 억제함
- 묵인해야 하는 경고가 발생하는 경우 붙이면 됨
- ```java
/*
@SuppressWarnings("deprecation") : @Deprecated가 붙은 대상을 사용해서 발생하는 경고 억제
@SuppressWarnings("unchecked") : 지네릭스를 사용하지 않아서 생하는 경고 억제
@SuppressWarnings("varags") : 가변인자의 타입이 지네릭 타입일 때 발생하는 경고 억제 - /// 중복 가능
@SuppressWarnings({"uncheked", "varags"}) - @SuppressWarnings("uncheked") // 지네릭스와 관련된 경고를 억제
ArrayList list = new ArrayList(); // 지네릭 타입을 지정하지 않음
list.add(obj)
- @SafeVarargs
- 메서드에 선언된 가변인자의 타입이 non-reifiable 타입일 경우 발생
static
이나final
이 붙은 메서드와 생성자에만 붙일 수 있음@SafeVarargs // unchecked 경고 억제 @SuppressWarnings("varags") // varags 경고 억제 public static <T> List<T> asList(T... a){ return new ArrayList<>(a); }
- @FunctionalInterface
- 함수형 인터페이스를 선언할 때, 올바르게 선언했는지 확인함
- 올바르게 선언하지 않은 경우 에러를 발생시킴
@FunctionalInterface public interface Runnable{ publlic abstract void run(); // 추상 메서드 }
- @Native
- 상수 필드에 붙이는 애너테이션임
- 네이티브 메서드는 JVM이 설치된 OS의 메서드를 말함
- 보통 C언어로 작성되어 있는데, 자바에서는 메서드의 선언부만 정의하고 구현하지 않음
- 단, JNI(Java Native Interface)를 이용하여 자바에 정의된 네이티브 메서드와 OS의 메서드를 연결하는 작업을 하고 있음
@Native public static final long MIN_VALUE = 0x8000000000000000L; // 최상위 클래스의 Object의 메서드 일부는 native임 public class Object{ private static native void registerNatives(); // 네이티브 메서드 static { registerNatives(); } protected native Object clone() throws CloneNotSupportedException; public final native Class<?> getClass(); public final native void notify(); public final native void notifyAll(); public final native void wait(long timeout) throws InterruptedException; public final native int hashCode(); ... }
- @Target*
- 애너테이션이 적용가능한 대상을 지저하는데 사용됨
- 종류
- ANNOTATION_TYPE : 애너테이션
- CONSTRUCTOR : 생성자
- FIELD : 필드(인스턴스 변수)
- LOCAL_VARIABLE : 지역변수
- METHOD : 메서드
- PACKAGE : 패키지
- PARAMETER : 매개변수
- TYPE : 타입(클래스, 인터페이스, enum)
- TYPE_PARAMETER : 타입 매개변수(JDK1.8)
- TYPE_USE : 타입이 사용되는 모든 곳(JDK1.8)
@Target({FIELD, TYPE}) public @interface MyAnootation{...}
- @Documented*
- 애너테이션에 대한 정보가 javadoc으로 작성한 문서에 포함되도록 함
@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ELEMENT.TYPE) public @interface FunctionalInterface{}
- @Inherited*
- 조상 클래스에 붙이면 자손 클래스도 이 애너테이션이 붙은 것과 같이 인식됨
@Inherited @interface SupperAnno{} @SuperAnno class Parent{} class Child extends Parents {}
- @Retention*
- 애너테이션이 유지되는 기간을 정함
- 종류
- SOURCE : 소스 파일에만 존재. 클래스 파일에는 존재하지 않음
- CLASS : 클래스 파일에 존재. 실행시에 사용불가. 기본값
- RUNTIME : 클래스파일에 존재. 싱행시에 사용가능
@Documented @Retention(RetentionPolicy.RUNTIME) // 런타임 @Target(ELEMENT.TYPE) public @interface FunctionalInterface{}
- @Repeatable*
- 애너테이션을 여러 번 붙을 ㅅ ㅜ있음
@Repeatable(ToDos.class) @interface Todo{ String value(); } @Todo("AAAA") @Todo("BBBB") // 반복 가능 class MyClass{...}
12.3.3 메타 애너테이션
- 애너테이션을 위한 애너테이션임
- 애너테이션의 적용대상(Target)이나 유지기간(Retention)등을 지정하는데 사용됨
12.3.4 애너테이션 타입 정의하기
- 정의 방법
@interface 애너테이션 이름 { 타입 요소이름(); // 애너테이션의 요소를 선언함 ... }
- 애너테이션의 요수는 반환값이 있고, 매개변수는 없는 추상 메서드의 형태임
- 요소들을 빠짐없이 지정해야 함
@interface TestInfo{ int count(); String testedBy(); ... } @TestInfo(count = 3, testedBy = "Kim", ...) public class NewClass{...}
- 값을 지정합지 않으면 기본값이 사용됨
@interface TEstInfo{ int count() default 1; // 기본값을 1로 지정 ... }
- 애너테이션의 요소가 오직 하나일 경우, 애너테이션을 적용할 때 요소의 이름 생략 가능
@interface TestInfo{ String value(); } @TestInfo("passed") public class NewClass{...}
- 요소의 타입이 배열인 경우 괄호 사용
@interface TestInfo{ String[] value(); } // 값이 여러 개인 경우 @TestInfo(value = {"passed", "TTT"}) public class NewClass{...} // 값이 하나인 경우 @TestInfo(value = "passed") public class NewClass{...}
12.3.5 java.lang.annotation.Annotation
- 모든 애너테이션의 조상은
Annotation
임 - 그러나, 애너테이션은 상속이 허용되지 않으므로 명시적으로 조상을 지정할 수 없음
@interface TestInfo extends Annotation {...} // 에러
Annotation
은 애너테이션이 아닌 일반적인 인터페이스로 정의되어 있음package java.lang.annotation; public interface Annotation{ // 일반적인 인터페이스 boolean equals(Object obj); int hashCode(); String toString(); Class<> extends Annotation> annotationType(); // 애너테이션 타입을 반환 }
- 모든 애너테이션의 조상인
Annotation
가 위와 같이 정의 되어있기 때문에,equals()
와 같은 메서드를 호출할 수 있음 Class<AnnotationTest> cls = AnnotationTest.class; Annotation[] annoArr = AnootationTest.class.getAnnotations(); for(Annotation a : annoArr){ System.out.println("toString()" + a.toString); ... }
- 요소가 하나도 정의되지 않은 애너테이션을 마커 애너테이션(Marker Annotation)이라 함
@Target(ElementType.METHOD) @Retention(RetentionPolicy.SOURCE) public @interface Override{} // 정의된 요소가 없음
- 애너테이션 요소의 규칙
- 요소의 타입은 기본형, String, enum, 애너테이션, Class만 허용됨
- ()안에 매개변수를 선언할 수 없음
- 예외를 선언할 수 없음
- 요소를 타입 매개변수로 정의할 수 없음
'자바의 정석 정리' 카테고리의 다른 글
자바의 정석 - 14.2 스트림 (0) | 2022.09.23 |
---|---|
자바의 정석 - 12.2 열거형(Enums) (0) | 2022.09.06 |
자바의 정석 - 12.1 지네릭스(Generics) (0) | 2022.09.06 |
자바의 정석 - 11.13 Collections (0) | 2022.09.05 |
자바의 정석 - 11.12 Properties (0) | 2022.09.05 |