충분히 쌓여가는
애너테이션 타입 정의하기, 애너테이션의 요소 본문
애너테이션 타입 정의하기
애너테이션을 직접 만들어 쓸 수 있다
@interface 애너테이션이름 {
타입요소이름(); // 애너테이션의 요소를 선언한다
...
}
예시
@interface DateTime {
String yymmdd();
String hhmmss();
}
애너테이션의 메서드는 추상 메서드이며, 애너테이션을 적용할 때 지정(순서 X)
@interface TestInfo {
int count();
String testBy();
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 제외)
@interface TestInfo {
int count() default 1; // 기본값을 1로 지정
}
@TestInfo // @TestInfo(count=1)과 동일
public class NewClass { ... }
요소가 하나이고 이름이 value일 때는 요소의 이름 생략 가능
@interface TestInfo {
String value();
}
@TestInfo("passed") // @TestInfo(value="passed")와 동일
class NewClass { ... }
요소의 타입이 배열인 경우, 괄호{}를 사용해야 한다
@interface TestInfo {
String[] testTools();
}
@Test(testTools={"JUnit", "AutoTester"})
@Test(testTools="JUnit")
@Test(testTools={}) // 값이 없을 때는 괄호{}가 반드시 필요
모든 애너테이션의 조상 - java.lang.annotation.Annotation
Annotation은 모든 애너테이션의 조상이지만 상속은 불가
@interface TestInfo extends Annotation { // 에러, 허용되지 않는 표현
int count();
String testedBy();
...
}
사실 Annotation은 인터페이스이다
package java.lang.annotation;
public interface Annotation { // Annotation 자신은 인터페이스이다
boolean equals(Object obj);
int hashCode();
String toString(0;
Class<? extends Annotation> annotationType(); // 애너테이션의 타입을 반환
}
Marker Annotation - 마커 애너테이션
요소가 하나도 정의되지 않은 애너테이션
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {} // 마커 애너테이션, 정의된 요소가 하나도 없다
@Target(ElementType.MEHTOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Test {} // 마커 애너테이션, 정의된 요소가 하나도 없다
@Test // 이 메서드가 테스트 대상임을 테스트 프로그램에게 알린다
public void method() {
...
}
애너테이션 요소의 규칙
애너테이션의 요소를 선언할 때 아래의 규칙을 반드시 지켜야 한다
1. 요소의 타입은 기본형, String, enum, 애너테이션, Class만 허용됨
2. 괄호() 안에 매개변수를 선언할 수 없다
3. 예외를 선언할 수 없다
4. 요소를 타입 매개변수<T>로 정의할 수 없다
잘못된 코드 예시
@interface AnnoTest {
int id = 100; // OK, 상수(기본형)
String major(int i, int j); // 에러, 매개변수 가질 수 없다
String minor() throws Exception; // 에러, 예외 선언 불가
ArrayList<T> list(); // 에러, 타입매개변수 사용 불가
}
코드
import java.lang.annotation.*;
@Deprecated
@SuppressWarnings("1111") // 유효하지 않은 애너테이션은 무시된다.
@TestInfo(testedBy="aaa", testTools= {"JUnit", "JUnit5"}, testDate=@DateTime(yymmdd="160101",hhmmss="235959"))
class annotationTest {
public static void main(String args[]) {
// annotationTest의 Class객체를 얻는다.
Class<annotationTest> cls = annotationTest.class;
TestInfo anno = cls.getAnnotation(TestInfo.class);
System.out.println("anno.testedBy()="+anno.testedBy());
System.out.println("anno.testDate().yymmdd()=" +anno.testDate().yymmdd());
System.out.println("anno.testDate().hhmmss()=" +anno.testDate().hhmmss());
for(String str : anno.testTools())
System.out.println("testTools="+str);
System.out.println();
// annotationTest에 적용된 모든 애너테이션을 가져온다.
Annotation[] annoArr = cls.getAnnotations();
for(Annotation a : annoArr)
System.out.println(a);
}
}
@Retention(RetentionPolicy.RUNTIME) // 실행 시에 사용가능하도록 지정
@interface TestInfo {
int count() default 1;
String testedBy();
String[] testTools() default "JUnit";
TestType testType() default TestType.FIRST;
DateTime testDate();
}
@Retention(RetentionPolicy.RUNTIME) // 실행 시에 사용가능하도록 지정
@interface DateTime {
String yymmdd();
String hhmmss();
}
enum TestType { FIRST, FINAL }
anno.testedBy()=aaa
anno.testDate().yymmdd()=160101
anno.testDate().hhmmss()=235959
testTools=JUnit
testTools=JUnit5
@java.lang.Deprecated(forRemoval=false, since="")
@TestInfo(count=1, testType=FIRST, testTools={"JUnit", "JUnit5"}, testedBy="aaa", testDate=@DateTime(yymmdd="160101", hhmmss="235959"))
'Java > JAVA3' 카테고리의 다른 글
쓰레드의 구현과 실행 (0) | 2023.08.02 |
---|---|
thread 쓰레드 (0) | 2023.08.02 |
메타 애너테이션 (0) | 2023.08.01 |
Annotation(애너테이션) @ (0) | 2023.07.31 |
열거형에 멤버 추가하기 (0) | 2023.07.31 |