코린이의 소소한 공부노트

애너테이션의 정의와 종류 본문

Java

애너테이션의 정의와 종류

무지맘 2022. 11. 17. 11:22

[애너테이션의 정의]

1. 애너테이션은 주석이라는 뜻

2. 우리가 일반적으로 사용하는 주석(/* */, //)처럼 프로그래밍 언어에 영향을 미치지 않는다.

3. 소스코드를 테스트하는 프로그램(JUnit)에게 유용한 정보를 제공한다.

/** <- 이것은 javadoc 주석
여기에 소스 코드에 대한 설명을
주루루루룩 쓰면
javadoc.exe 파일이 주석을 추출해서
문서를 만든다.
*/
public class Sample { }

// 애너테이션 사용 예시
@Test // JUint에게 이 메서드가 테스트 대상임을 알린다.
public void method() { }

java 에서 제공하는 애너테이션. * 이 붙은 것은 메타 애너테이션(애너테이션을 만드는 애너테이션)

 

[표준 애너테이션]

1. @Override

1) 오버라이딩을 올바르게 했는지 컴파일러가 체크하게 한다.

2) 오버라이딩할 때 메서드 이름을 잘못 적는 실수를 방지하기 위해 오버라이딩할 때는 메서드 선언부 앞에 @Override를 붙이는 것이 좋다.

class Parent {
    void parentMethod() { }
}

class Child extends Parent{
    @Override // 이 부분을 주석처리하면 아래 코드는 컴파일 단계에서는 OK. 실행 시 에러 발생
    void parentmethod() { } // 오버라이딩 하려다가 메서드 이름을 잘못 적음
}

// 위 코드의 컴파일 결과
AnnotationTest.java:5: error: method does not override or implement a method from a supertype
    @Override
     ^ 1 error

2. @Deprecated

1) 앞으로 사용하지 않을 것을 권장하는 필드나 메서드에 붙인다.

  - 대표적으로 Date 클래스의 getDate()가 있다.

2) 자바는 하위 호환성을 중요하게 생각하기 때문에 없애기보다는 사용하지 않는 것을 권장하는 편이다.

@Deprecated
public int getDate() { return normalize().getDayOfMonth(); }
// As of JDK version 1.1, replaced by Calender.get(Calendar.DAY_OF_MONTH).

3) @Deprecated가 붙은 대상이 사용된 코드를 컴파일하면 나오는 메시지

Note: AnnotationTest.java uses or override a deprecated API. // 에러X, 경고O
Note: Recompile with –Xlint:deprecation for details.

// 위의 옵션을 넣고 다시 컴파일 하면 나오는 상세 메시지
AnnotationTest.java:10: warning: [deprecation] ...

3. @FunctionalInterface

1) 함수형 인터페이스에 붙이면 컴파일러가 올바르게 작성했는지 체크한다.

2) 함수형 인터페이스는 하나의 추상 메서드만 가질 수 있다는 제약이 있다.

@FunctionalInterface
public interface Runnable{
    public abstract void run(); // 추상메서드
    void test(); // 추상메서드가 1개 더 생기면 컴파일 에러 발생
}

4. @SuppressWarnings

1) 컴파일러의 경고 메시지가 나타나지 않게 억제한다.

2) 괄호() 안에 억제하고자 하는 경고의 종류를 문자열로 지정하면 된다.

@SuppressWarnings(“unchecked”) // 지네릭스와 관련된 경고를 억제
ArrayList list = new ArrayList(); // 지네릭 타입을 지정하지 않았지만 경고 발생X
list.add(obj); // 여기서 경고가 발생

3) 둘 이상의 경고를 동시에 억제하려면 중괄호{}를 이용해야 한다.

@SuppressWarnings({“deprecation”, “unchecked”, “varargs”})

4) -Xlint 옵션으로 컴파일하면 경고 메시지를 확인할 수 있다.

// 대괄호[] 안이 경고의 종류를 나타낸다. 아래 메시지의 경우 경고의 종류는 rawtypes
AnnotationTest.java:10: warning: [rawtypes] found raw type: List
    public static void sort(List list){
                            ^
missing type arguments for generic class Lst<E>
where E is a type-variable: E extends Object declared in interface List

// @SuppressWarnings(“rawtypes”)를 붙이면 더이상 이 경고 메시지는 나오지 않는다.

  

[메타 애너테이션]

1. @Target

1) 애너테이션이 적용 가능한 대상을 지정하는 데 사용한다.

@Target({TYPE, FIELD, TYPE_USE}) // 적용 대상이 TYPE, FIELD, TYPE_USE
public @interface MyAnno { } // 애너테이션 정의
 
@MyAnno
class Test{ // 클래스(TYPE)
    @MyAnno
    int i; // 멤버변수(FIELD)
 
    @MyAnno
    Test t; // TYPE_USE
}

2. @Retention

1) 애너테이션이 유지되는 기간을 지정하는 데 사용한다.

2) 컴파일러에 의해 사용되는 애너테이션의 유지 정책은 SOURCE이다.

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override { }
// Override는 컴파일러가 체크하고 끝나기 때문에
// 굳이 런타임까지 유지할 필요가 없다.

3) 실행 시에 사용 가능한 애너테이션의 정책은 RUNTIME이다.

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FunctionalInterface { }
// 컴파일러도 체크하지만 실행시에도 사용한다.

3. @Documented

1) 애너테이션 정보가 javadoc으로 적성된 문서에 포함되게 한다.

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

4. @Inherited

1) 애너테이션이 자손 클래스에 상속되도록 한다.

@Inherited // @SupperAnno가 자손까지 영항을 미치게 한다.
@interface SupperAnno { }
 
@SuperAnno
class Parent{}
 
class Child extends Parent { } // 쓰진 않았지만 Child에 애너테이션이 붙은 것과 같다.

5. @Repeatable

1) 애너테이션을 반복해서 적용할 수 있게 한다.

@Repeatable(ToDos.class) // ToDo 애너테이션을 반복해서 사용 가능
@interface ToDo{
String value();
}
 
@ToDo(“delete test codes.”) // @Repeatable을 붙였으므로 여러번 사용 가능
@ToDo(“overried inherited methods”)
class MyClass { }

2) 위에서 @Repeatable@ToDo를 하나로 묶는 컨테이너 애너테이션도 정의해야 한다.

@interface Todos{ // 애너테이션이름 + s -> 컨테이너 애너테이션
    ToDo[] value(); // @Todo타입의 배열 선언. 이름이 반드시 value여야 한다.
}

[쿠키글] 기타 애너테이션

1. @Native

1) navite 메서드에서 참조되는 상수 앞에 붙인다.

@Native public static final long MIN_VALUE = 0x8000000000000000L;

2) JVM이 native 메서드(OS 메서드)를 잘 쓸 수 있게 해주는 것이 JNI(Java Native Interface, 다른 프로그래밍 언어와 연동해주는 )이다.

public class Object{
    private static native void registerNatives(); // native 메서드
    static{
        registerNatives(); // native 메서드 호출
    }
    protected native Object clone() throws CloneNotSupportedException;
    public final native Class<?> getCalss();
    public final native void notify();
    public final native void notifyAll();
    public final native void wait(long timeout) throws InterruptedException;
    public native int hashCode();
    ...
}

2. @SafeVarargs

1) 가변 인자의 타입이 non-reifiable인 경우 발생하는 unchecked 경고를 억제한다.

2) 생성자 또는 static이나 final이 붙은 메서드에만 붙일 수 있다.

  - , 오버라이딩이 가능한 메서드에는 사용할 수 없다.

3) @SafeVarargs에 의한 경고의 억제를 위해 @SuppressWarnings를 사용한다.

@SafeVarargs // ‘unchecked’ 경고를 억제한다.
@SuppressWarnings(“varargs”) // ‘varargs’ 경고를 억제한다.
public static <T> List<T> asList(T... a){
    return new ArrayList<>(a);
}

'Java' 카테고리의 다른 글

쓰레드의 정의  (0) 2022.11.24
애너테이션 만들기  (0) 2022.11.21
열거형(enum, enumerated type)  (0) 2022.11.17
지네릭 타입의 형변환과 제거  (0) 2022.11.14
와일드카드 ?와 지네릭 메서드  (0) 2022.11.14