이펙티브 자바 아이템 27 - 비검사 경고를 제거하라 - 완벽 공략
아이템 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
은 자바 모듈을 이야기한다.
애노테이션을 어떻게 정의하느냐에 따라 애노테이션의 정보를 참조하는 시기가 다르고 선언하는 위치가 다르게 된다.