본문 바로가기
개발 관련 강의 정리/자바의정석

[자바의정석] 애너테이션 정리

by 코딩개발 2023. 4. 19.
728x90
반응형

[자바의 정석 - 기초편] ch12-23~26 표준애너테이션

package test;

class Parent {
    void parentMethod() {

    }
}

class Child extends Parent {
    @Override
    @Deprecated
    void parentMethod() {

    }
}

@FunctionalInterface // 함수형 인터페이스는 하나의 추상 메서드만 가능
interface Testable {
    void test(); // 추상 메서드
//    void check(); // 추상 메서드
}



public class Test {
    public static void main(String[] args) {
        Child c = new Child();
        c.parentMethod(); // deprecated된 메서드 사용
    }
}

 
@Deprecated
앞으로 사용하지 않을 것을 권장하는 필드나 메서드에 붙인다.
ex) Date 클래스의 getDate()

@FunctionalInterface
함수형 인터페이스에 붙이면, 컴파일러가 올바르게 작성했는지 체크
함수형 인터페이스에는 하나의 추상메서드만 가져야 한다는 제약이 있음
 

 

package test;

class Parent {
    void parentMethod() {

    }
}

class Child extends Parent {
    @Override
    @Deprecated
    void parentMethod() {

    }
}

@FunctionalInterface
interface Testable {
    void test();
//    void check();
}



public class Test {
    @SuppressWarnings("deprecation") // 추가
    public static void main(String[] args) {
        Child c = new Child();
        c.parentMethod();
    }
}

 


@SuppressWarnings
컴파일러 경고메시지가 나타나지 않게 억제한다.
 


[자바의 정석 - 기초편] ch12-29~33 메타애너테이션
 
메타 애너테이션 : 애너테이션을 위한 애너테이션
java.lang.annotation패키지에 포함
 
@Target
애너테이션을 정의할 때, 적용대상 지정에 사용

 

@Target({TYPE, FIELD, TYPE_USE}) // 적용대상이 TYPE, FIELD, TYPE_USE
public @interface MyAnnotation { } // MyAnnotation을 정의

@MyAnnotation // 적용대상이 TYPE인 경우
class MyClass {
    @MyAnnotation // 적용대상이 FIELD인 경우
    int i;
    
    @MyAnnotation // 적용대상이 TYPE_USE인 겅우
    MyClass mc;
}

 
@Retention
애너테이션이 유지(retention)되는 기간을 지정하는데 사용

유지 정책 의미
SOURCE 소스 파일에만 존재. 클래스파일에는 존재하지 않음
CLASS 클래스 파일에 존재. 실행시에 사용불가. 기본값
RUNTIME 클래스 파일에 존재. 실행시에 사용가능.

ex)

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {}

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FunctionalInterface() {}

 
@Documented
javadoc으로 작성한 문서에 포함시킬 때 사용
 
@Inherited
애너테이션을 자손 클래스에 상속하고자 할 때 사용

@Inherited
@interface SuperAnno {}

@SuperAnno
class Parent {}

// @SuperAnno 가 붙은 것으로 인식
class Child extends Parent {}

 
@Repeatable
반복해서 붙일 수 있는 애너테이션을 정의할 때 사용

@Repeatable(ToDos.class) // ToDo애너테이션을 여러 번 반복해서 쓸 수 있게 한다.
@interface  ToDo {
    String value();
}

@Repeatable이 붙은 애너테이션은 반복해서 붙일 수 있다.

@ToDo("delete test codes")
@ToDo("override inherited methods")
class MyClass {
    ...
}

@Repeatable인 @ToDo를 하나로 묶을 컨테이너 애너테이션도 정의해야 함

@interface ToDos { // 여러 개의 ToDo애너테이션을 담을 컨테이너 애너테이션 ToDos
    ToDo[] value(); // ToDo애너테이션 배열타입의 요소를 선언. 이름이 반드시 value이어야 함
}

 


[자바의 정석 - 기초편] ch12-34~37 애너테이션 타입 정의하기, 애너테이션의 요소
 
애너테이션 타입 정의하기
- 애너테이션을 직접 만들어 쓸 수 있다.

@interface 애너테이션이름 {
    타입 요소이름(); // 애너테이션의 요소를 선언 / 추상 메서드, 애너테이션을 적용할 때 지정(순서X)
    ...
}

 
- 애너테이션의 메서드는 추상 메서드이며, 애너테이션을 적용할 때 지정(순서X)

enum TestType {FIRST, FINAL}

@interface DateTime {
    String yymmdd(); // day
    String hhmmss(); // time
}

@interface TestInfo {
    int count();
    String testedBy();
    String[] testTools();
    TestType testType(); // enum TestType {FIRST, FINAL}
    DateTime testDate(); // 자신이 아닌 다른 애너테이션(@DateTime)을 포함할 수 있다.

}

// 순서X
@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;
}

@TestInfo // @TestInfo(count=1)과 동일
public class NewClass { ... }

- 요소가 하나이고 이름이 value일 때는 요소의 이름 생략가능

@interface TestInfo {
    String value();
}

@TestInfo("passed") // @TestInfo(value="passed")와 동일
class NewClass { ... }

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

@interface TestInfo {
    String[] testTools();
}

@TestInfo(testTools = {"JUnit", "AutoTester"})
@TestInfo(testTools = "JUnit")
@TestInfo(testTools = {}) // 값이 없으 때는 괄호{}가 반드시 필요

 
모든 애너테이션의 조상(인터페이스)

public interface Annotation {
    boolean equals(Object obj);
    int hashCode();
    String toString();

    Class<? extends Annotation> annotationType();
}

 
마커 애너테이션
- 요소가 하나도 정의되지 않은 애너테이션

public @interface Override {} // 마커 애너테이션. 정의된 요소가 하나도 없다.
public @interface Test {} // 마커 애너테이션. 정의된 요소가 하나도 없다.

@Test // 이 메서드가 테스트 대상임을 테스트 프로그램에게 알린다.
public void method() {
	...
}

 
애너테이션 요소의 규칙
- 요소의 타입은 기본형, String, enum, 애너테이션, Class만 허용된
- 괄호() 안에 매개변수를 선언할 수 없다.
- 예외를 선언할 수 없다.
- 요소를 타입 매개변수로 정의할 수 없다.

@interface AnnoTest {
	int id = 100;
    String major(int i, int j); // 매개변수 불가능 : (int i, int j)
    String minor() throws Exception; // 예외 불가능 : throws Exception
    ArrayList<T> list(); // 요소를 타입 매개변수로 정의X : <T>
}

 
 
실습

enum TestType {FIRST, FINAL}

@interface DateTime {
    String yymmdd(); // day
    String hhmmss(); // time
}

@Retention(RetentionPolicy.RUNTIME)
@interface TestInfo {
    int count() default 1;
    String testedBy();
    String[] testTools() default "JUnit";
    TestType testType() default TestType.FIRST;
    DateTime testDate();
}

@Deprecated
@SuppressWarnings("1111") // 유효하지 않은 애너테이션은 무시된다.
@TestInfo(testedBy = "aaa",
        testTools = {"JUnit", "JUnit5"},
        testDate = @DateTime(yymmdd = "160101", hhmmss = "235959")
)
public class Test {
    public static void main(String[] args) {
        // AnnotaionEx5의 Class객체를 얻는다.
        Class<Test> cls = Test.class;

        TestInfo anno = (TestInfo)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();

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

        for(Annotation a : annoArr)
            System.out.println(a);
    }
}

결과

 


참고
[자바의 정석 - 기초편]
https://www.youtube.com/watch?v=7eX1EB76Dio&list=PLW2UjW795-f6xWA2_MUhEVgPauhGl3xIp&index=145&ab_channel=%EB%82%A8%EA%B6%81%EC%84%B1%EC%9D%98%EC%A0%95%EC%84%9D%EC%BD%94%EB%94%A9
 
https://www.youtube.com/watch?v=7eX1EB76Dio&list=PLW2UjW795-f6xWA2_MUhEVgPauhGl3xIp&index=145&ab_channel=%EB%82%A8%EA%B6%81%EC%84%B1%EC%9D%98%EC%A0%95%EC%84%9D%EC%BD%94%EB%94%A9
 
https://www.youtube.com/watch?v=p7KStWk8hWU&list=PLW2UjW795-f6xWA2_MUhEVgPauhGl3xIp&index=146&ab_channel=%EB%82%A8%EA%B6%81%EC%84%B1%EC%9D%98%EC%A0%95%EC%84%9D%EC%BD%94%EB%94%A9
 
https://www.youtube.com/watch?v=81U0MyuZQKo&list=PLW2UjW795-f6xWA2_MUhEVgPauhGl3xIp&index=147&ab_channel=%EB%82%A8%EA%B6%81%EC%84%B1%EC%9D%98%EC%A0%95%EC%84%9D%EC%BD%94%EB%94%A9
 
 
 

728x90
반응형

댓글