코린이의 소소한 공부노트

애너테이션 만들기 본문

Java

애너테이션 만들기

무지맘 2022. 11. 21. 16:27

[애너테이션 타입 정의하기]

1. 애너테이션을 직접 만들어 쓸 수 있다.

@interface 애너테이션이름{
    타입 요소이름(); // 애너테이션의 요소 선언
    ...
}

2. 애너테이션의 메서드는 추상 메서드이며, 구현할 필요가 없다.

3. 애너테이션을 적용할 때 모두 지정해야 한다.. 이름과 값을 다 지정하기 때문에 순서는 상관없다.

@interface DateTime{
    String yymmdd();
    String hhmmss();
}
 
@interface TestInfo {
    int count();
    String testedBy();
    String[] testTools();
    TestType testType(); // enum TestType { FIRST, FINAL }
    DateTime testDate(); // 자신이 아닌 다른 애너테이션 포함 가능
}
 
// @TestInfo 사용 예시
@TestInfo(
    count=3, testedBy=“Kim”, testTools={“JUnit”, “AutoTester”},
    testType=TestType.FIRST;
    testDate=@DateTime(yymmdd=“221121”, hhmmss=“145539”) )
publie class NewClass { }

 

[애너테이션 요소의 기본값]

1. 애너테이션을 적용할 때 값을 지정하지 않았다면 사용될 수 있는 기본값을 지정할 수 있다.(null 제외)

@interface TestInfo{
    int count() default 1; // 기본값을 1로 지정
}
 
@TestInfo // @TestInfo(count=1)과 동일
public class NewClass { }

2. 요소가 1개이고 이름이 value일 때는 요소의 이름을 생략할 수 있다.

@interface TestInfo{
    String value();
}
 
@TestInfo(“pass”) // @TestInfor(value=“pass”)와 동일
public class NewClass { }

3. 요소의 타입이 배열인 경우 괄호{}를 사용해야 한다.

@interface TestInfo{
    String[] info() default {“aaa”,“bbb”}; // 기본값이 여러 개인 경우
    String[] info2() default “ccc”; // 기본값이 하나인 경우 괄호 생략 가능
}
 
@TestInfo // @TestInfo(info={“aaa”,“bbb”}, info2=“ccc”)와 동일
class NewClass { }
 
@TestInfo(info2={}) // @TestInfo(info={“aaa”,“bbb”}, info2={})와 동일
// 빈 배열이라면 반드시 괄호{}가 필요
class NewClass2 { }

 

[Annotation 인터페이스]

1. java.lang.annotation에 있다.

2. Annotation은 모든 애너테이션의 조상이지만 상속은 할 수 없다.

@interface TestInfo extends Annotation { } // 에러

3. Annotation 인터페이스의 코드는 다음과 같다.

package java.lang.annotation;
 
public interface Annotation{ // 추상 메서드는 구현하지 않지만 사용은 가능하다.
    boolean equals(Object obj);
    int hashCode();
    String toString();

    Class<? extends Annotation> annotationType(); // 애너테이션의 타입을 반환한다.
}

 

[마커 애너테이션(marker annotation)]

1. 요소가 하나도 정의되지 않은 애너테이션

2. 요소가 없기 때문에 “@애너테이션이름”만 쓰면 된다.

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {} // 정의된 요소가 하나도 없다.
 
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Test {} // 정의된 요소가 하나도 없다.

 

[애너테이션 요소의 규칙]

- 애너테이션의 요소를 선언할 때 다음 규칙을 꼭 지켜야 한다.

1. 요소의 타입은 기본형, String, enum, 애너테이션, Class만 허용된다.

2. 괄호()안에 매개변수를 선언할 수 없다.

3. 예외를 선언할 수 없다.

4. 요소를 타입 매개변수로 정의할 수 없다.

@interface AnnoTest{
    int id = 100; // OK. 상수 선언. static final int id = 100; 과 동일한 코드
    String major(int i, int j); // 에러. 매개변수 선언 불가
    String minor() throws Exception; // 에러. 예외 선언 불가
    ArrayList<T> list(); // 에러. 타입 매개변수 사용 불가
}

 

[애너테이션 사용 예시 총정리]

@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 }

// Test 클래스에 붙인 애너테이션 목록
@Deprecated
@SuppressWarnings("1111") // 유효하지 않은 애너테이션은 무시된다.
@TestInfo(testedBy="aaa", testDate=@DateTime(yymmdd="221121",hhmmss="145539"))
// testTools와 testType은 기본값

// Test 클래스 main()

// Test의 Class 객체를 얻는다.
Class<Test> cls = Test.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);
// anno.testedBy()= aaa
// anno.testDate().yymmdd()= 221121
// anno.testDate().hhmmss()= 145539
// testTools= JUnit

// Test 클래스에 적용된 모든 애너테이션을 가져온다.
Annotation[] annoArr = cls.getAnnotations();

for(Annotation a : annoArr)
    System.out.println(a);
// @java.lang.Deprecated(forRemoval=false, since="")
// @TestInfo(count=1, testType=FIRST, testTools={"JUnit"}, testedBy="aaa", testDate=@DateTime(yymmdd="221121", hhmmss="145539"))
// SuppressWarnings 애너테이션은 유효하지 않아 무시되고 출력되지 않았다.

'Java' 카테고리의 다른 글

쓰레드의 구현 방법과 실행  (0) 2022.11.30
쓰레드의 정의  (0) 2022.11.24
애너테이션의 정의와 종류  (0) 2022.11.17
열거형(enum, enumerated type)  (0) 2022.11.17
지네릭 타입의 형변환과 제거  (0) 2022.11.14