개발 공부/Java

이펙티브 자바 아이템 27 - 비검사 경고를 제거하라 - 완벽 공략

개발인생 2022. 12. 9. 09:53
반응형

아이템 27 - 비검사 경고를 제거하라 - 완벽 공략

이 글은 백기선 님의 이펙티브 자바 강의와 이펙티브 자바 3 / E 편을 참고하여 작성하였습니다.

에너테이션


@Documented
public @interface MyAnnotation {

}

@Documented 을 붙여주면 해당 애노테이션을 사용한 자바 코드의 javadoc 을 만들 때

해당 애노테이션 정보가 포함된다.


@Retention

@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {

}

@Retention 은 해당 애노테이션의 정보를 언제까지 참조할 수 있게 할 것이냐에 대한 설정이다.

총 3가지가 있다.

  • Runtime

기본값이며 가장 폭이 넓다.

애노테이션을 사용한 코드에서 해당 애노테이션 정보를 Runtime 중에도 이용할 수 있도록 한다.

@MyAnnotation
public class MyClass {

    public static void main(String[] args) {
        Arrays.stream(MyClass.class.getAnnotations()).forEach(System.out::println);
    }
}

Runtime 중에도 참고하고 싶으면 애노테이션의 @Retention(RetentionPolicy.RUNTIME) 을 붙여준다.

  • Class
@Retention(RetentionPolicy.CLASS)
public @interface MyAnnotation {

}

@Retention(RetentionPolicy.CLASS) 을 붙이면 자바 컴파일 후 생기는 클래스 파일까지만 참조할 수 있게 한다.

Runtime 중에는 참조할 수 없다.

Runtime 은 클래스 파일에 있는 바이트 코드를 JVM 이 읽어들여서(클래스 로딩) JVM 의 메모리로 읽어들인 상태이다.

@Retention(RetentionPolicy.CLASS) 를 붙여오면 JVM 의 메모리로 읽어올 때 해당 애노테이션의 정보를 읽어오지 않는다.

바이트 코드에 접근하는 라이브러리를 이용하면 @Retention(RetentionPolicy.CLASS) 를 붙여도 해당 정보를 읽어올 수 있다.

  • Source
@Retention(RetentionPolicy.SOURCE)
public @interface MyAnnotation {

}

애노테이션을 어떠한 정보를 표시하는 주석같은 역활로 사용한다면 @Retention(RetentionPolicy.SOURCE) 를 붙여준다.

가장 좁은 범위로 바이트 코드에서도 참조하지 않게 된다.


@Target

@Target 은 애노테이션을 어디에 사용할 수 있는지 선언하는 것이다.

배열로 여러군데를 설정할 수 있다.

@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.TYPE})
public @interface MyAnnotation {

}

@Target({ElementType.TYPE}) 은 타입에만 선언할 수 있게 된다.

@MyAnnotation
public class MyClass {

    @MyAnnotation // 에러
    public static void main(String[] args) {
        Arrays.stream(MyClass.class.getAnnotations()).forEach(System.out::println);
    }
}

타입에만 선언해야하기 때문에 메서드에는 선언 할 수 없다.

@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface MyAnnotation {

}
@Target({ElementType.TYPE, ElementType.METHOD})

위와 같이 ElementType.METHOD 를 추가로 전달해 메서드에서도 선언이 가능하게 할 수 있다.

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, MODULE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
    /**
     * The set of warnings that are to be suppressed by the compiler in the
     * annotated element.  Duplicate names are permitted.  The second and
     * successive occurrences of a name are ignored.  The presence of
     * unrecognized warning names is <i>not</i> an error: Compilers must
     * ignore any warning names they do not recognize.  They are, however,
     * free to emit a warning if an annotation contains an unrecognized
     * warning name.
     *
     * <p> The string {@code "unchecked"} is used to suppress
     * unchecked warnings. Compiler vendors should document the
     * additional warning names they support in conjunction with this
     * annotation type. They are encouraged to cooperate to ensure
     * that the same names work across multiple compilers.
     * @return the set of warnings to be suppressed
     */
    String[] value();
}

SuppressWarnings 애노테이션의 설정을 보면 적용범위는 Source 로 정의되어 있다.

때문에 해당 애노테이션의 정보는 컴파일 할 때에만 사용되게 된다.

컴파일 이후에는 의마가 없는 애노테이션이기 때문에 적용범위가 Source 인 것이다.

타겟은 @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, MODULE}) 로 설정되어있다.

LOCAL_VARIABLE 은 변수 선언에 애노테이션을 사용할 수 있게 해준다.

MODULE 은 자바 모듈을 이야기한다.

애노테이션을 어떻게 정의하느냐에 따라 애노테이션의 정보를 참조하는 시기가 다르고 선언하는 위치가 다르게 된다.

반응형