[작성일: 2023. 02. 08]
애너테이션
- 주석처럼 프로그래밍 언어에 영향을 미치지 않으며 유용한 정보(설정 정보 등)를 제공하는 것.
@Test // 이 메서드가 테스트 대상임을 테스트 프로그램에게 알림 (JUnit)
public void method() {
...
}
표준 애너테이션
@Override
- 컴파일러에게 오버라이딩하는 메서드라는 것을 알림.
- 오버라이딩을 올바르게 했는지 컴파일러가 체크하게 함.
- 오버라이딩 할 때 메서드 이름을 잘못 적는 실수 하는 경우가 많으니 사용해 볼 것.
class Parent { void parentMethod() {} } class Child extends Prent { @Override boid parentMethod() {} }
@Deprecated
- 앞으로 사용하지 않을 것을 권장하는 필드나 메서드에 붙임. (취소선 나타남)
- @Deprecated의 사용 예 : Date 클래스의 getDate()
- @Deprecated를 붙인 코드를 컴파일하면 경고메시지가 나옴.@Deprecated public int getDate() { return normalize().getDayOfMonth(); }
@SuppressWarnings
- 컴파일러의 경고메세지가 나타나지 않게 억제함.
- 괄호() 안에 억제하고자 하는 경고의 종류를 문자열로 지정함.
- 둘 이상의 경고를 동시에 억제 가능.
- '-Xlint' 옵션으로 컴파일하면 경고메시지를 확인할 수 있음.@SuppressWarnings("unchecked") // 지네릭스와 관련된 경고를 억제 ArrayList list = new ArrayList(); // 지네릭 타입 지정하지 않음. list.add(obj) ; // 여기서 경고 발생
@FunctionalInterface
- 함수형 인터페이스에 붙이면 컴파일러가 올바르게 작성했는지 체크함.
- 함수형 인터페이스는 하나의 추상메서드만 가져야 한다는 제약이 있음.@FunctionalInterface // 하나의 추상 메서드만 사용 가능 public interface Runnable { public abstract void run(); // 추상메서드 }
표준 애너테이션 | 설명 |
@Override | 컴파일러에게 오버라이딩하는 메서드라는 것을 알림 |
@Deprecated | 앞으로 사용하지 않을 것을 권장하는 필드나 메서드에 붙임. |
@SuppressWarnings | 컴파일러의 특정 경고메세지가 나타나지 않게 해줌. |
@SafeVarargs | 지네릭스 타입의 가변인자에 사용함.(JDK 1.7) |
@FunctionalInterface | 함수형 인터페이스라는 것을 알림. (JDK 1.8) |
@Native | native 메서드에서 참조되는 상수 앞에 붙임. (JDK 1.8) |
메타 애너테이션
- '애너테이션을 위한 애너테이션'
- 애너테이션을 만들 때 사용하는 애너테이션
- 메타 애너테이션은 java.lan.annotation 패키지에 포함됨.
@Target
- 애너테이션을 정의할 때, 적용 대상 지정에 사용함.
- 오버라이딩을 올바르게 했는지 컴파일러가 체크하게 함.
- 오버라이딩 할 때 메서드 이름을 잘못 적는 실수 하는 경우가 많으니 사용해 볼 것.
@TARGET( {TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE} ) @Retention(RetentionPolicy.SOURCE) public @interface SuppressWarnings { String[] value(); }
@Retention
- 애너테이션이 유지되는 기간을 지정하는 데 사용함.
- 컴파일러에 의해 사용되는 애너테이션의 유지 정책은 SOURCE
- 실행 시에 사용 가능한 애너테이션의 정책은 RUNTIME
유지 정책 의미 SOURCE 소스 파일에만 존재
클래스 파일에는 존재하지 않음.CLASS 클래스 파일에 존재
실행시에 사용불가, 기본값RUNTIME 클래스 파일에 존재
실행시에 사용 가능@Target(ElementType.METHOD) @Retention(RetentionPolicy.SOURCE) public @interface Override {} @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface FunctionalInterface {}
@Documented
- javadoc으로 작성한 문서에 포함시키려면 @Documented를 붙임.
@Inherited
- 애너테이션을 자손 클래스에 상속하고자 할 때 붙임@Inherited // SuperAnno가 자손까지 영양미치게 함. @interface SuperAnno {} @SuperAnno class Parent {} class Child extends Parent {} // Child에 애너테이션이 붙은 것으로 인식
@Repeatable
- 반복해서 붙일 수 있는 애너테이션을 정의할 때 사용함.
- @Repeatable이 붙은 애너테이션은 반복해서 붙일 수 있음.
- @Repeatable인 @ToDo를 하나로 묶을 컨테이너 애너테이션도 정의해야 함.@Repeatable(ToDos.class) // ToDo 애너테이션을 여러 번 반복해서 사용 @interface ToDo { String value(); } @ToDo("delete test codes.") @ToDo("override inherited methods") class MyClass { ... } @interface ToDos { // 여러 개의 ToDo애너테이션을 담을 컨테이너 애너테이션 ToDos ToDo[] value(); // ToDo 애너테이션 배열타입의 요소 선언. 이름이 반드시 value여야 함. }
메타 애너테이션 | 설명 |
@Target | 애너테이션이 적용가능한 대상을 지정하는데 사용함. |
@Documented | 애너테이션 정보가 javadoc으로 작성된 문서에 포함되게 함. |
@Inherited | 애너테이션이 자손 클래스에 상속되도록 함. |
@Retention | 애터네이션이 유지되는 범위를 지정하는데 사용함. |
@Repeatable | 애터네이션을 반복해서 적용할 수 있게 함. (JDK 1.8) |
애너테이션 타입 정의하기
- 애너테이션을 직접 만들어 쓸 수 있음.
- 애너테이션의 메서드는 추상 메서드이며, 애너테이션을 적용할 때 지정(순서 X)
- 추상 메서드를 구현할 필요는 없음.
@interface 애너테이션이름 {
타입 요소이름(); // 애너테이션의 요소 선언
...
}
@interface TestInfo {
int count();
String testedBy();
String[] testTools();
TestType testType(); // enum testType { FIRST, FINAL }
DateTime testDate(); // 자신이 아닌 다른 애너테이션(@DateTime)을 포함할 수 있음.
}
@TestInfo (
count=3, testedBy = "Kim",
testTool = ("JUnit", "AutoTester"),
testType = TestType.FIRST,
testDate=@DateTime(yymmdd="221111", hhmmss = "111111")
}
public class NewClass {...}
애너테이션의 요소
- 적용 시 값을 지정하지 않으면 사용될 수 있는 기본값 지정 가능(null 제외)
- 요소가 하나이고 이름이 value일 때 요소의 이름 생략 가능.
- 요소의 타입이 배열인 경우, 괄호{}를 사용해야 함.
@interface TestInfo {
int count() default 1;
}
@TestInfo
public class NewClass {...}
@interface TestInfo {
String value();
}
@TestInfo("passed")
class NewClass {...}
@interface TestInfo {
String[] testTools();
}
@Test(testTools={})
애너테이션의 조상
- java.lang.annotation.Annotation.
- Annotation은 모든 애너테이션의 조상이지만 상속은 불가능함.
- Annotation은 인터페이스임.
@interface TestInfo extends Annotation { // 에러. 허용되지 않는 표현
}
package java.lang.annotation;
public interface Annotation { // Annotation 자신은 인터페이스임.
boolean equals(Object obj);
int hashCode();
String toString();
class<? extends Annotation> annotationType(); // 애너테이션 타입 반환
}
마커 애너테이션(Marker Annotation)
- 요소가 하나도 정의되지 않은 애너테이션
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {} // 마커 애너테이션. 정의된 요소가 하나도 없음.
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Test {} // 마커 애너테이션. 정의된 요소가 하나도 없음.
애너테이션 요소의 규칙
- 요소의 타입은 기본형, String, enum, 애너테이션, Class만 허용됨.
- 괄호() 안에 매개변수 선언 불가능 - 추상 메서드
- 예외 선언 불가능
- 요소를 타입 매개변수로 정의할 수 없음. <T>
🐣 해당 게시글은 자바의 정석(남궁성 님) 영상으로 함께 공부하며 요약/정리한 글입니다.
🐣 입문 개발자가 작성한 글이므로 틀린 내용이나 오타가 있을 수 있습니다.