# ITEM27 비검사 경고를 제거하라

# 제너렉의 컴파일 경고들

  • 비검사 형변환 경고
  • 비검사 메서드 호출 경고
  • 비검사 매개변수화 가변인수타입 경고
  • 비검사 변환 경고

# unchecked warning

unchecked warning, 확인되지 않은 경고, 비검사 경고

cast 로 인해, 프로그램이 다른 곳에서 예외를 throw 할 수 있음을 프로그래머에게 알려준다.

  • 비검사 경고를 모두 제거했을 때
    • 타입 안전성 보장
    • 런타임에 ClassCastException 이 나타나지 않고 의도대로 잘 동작한다.

# 비검사 경고 제거

new HashSet() 의 타입 매개변수를 명시하지 않았다.

Set<Lark> exaltation = new HashSet();
1

다음은 잘못된 코드임을 컴파일러를 통해 알 수 있다.
(javac 명령줄 인수에 -Xlint:uncheck 옵션 추가)

...java:line: waring: [unchecked] unchecked conversion
    Set<Lark> exaltation = new HashSet();
required: Set<Lark>
found: HashSet
1
2
3
4
Set<Lark> exaltation = new HashSet<Lark>();
1

혹은 자바7 부터, 다이아몬드 연산자<> 사용 → 컴파일러가 타입 매개변수 추론

Set<Lark> exaltation = new HashSet<>();
1

# @Suppress Warnings("unchecked")

# 사용 상황

  • 경고를 제거할 수는 없고,
  • 타입 안전의 확신이 있을 경우
    • 경고를 무시해도 안전한 이유를 항상 주석으로 남겨야 한다.

위와 같은 경우에 사용을 하지 않으면,

  • 제거하지 않은 수 많은 경고 → 진짜 문제를 알리는 새로운 경고가 파묻힐 수도 있음

# 사용 범위

모든 선언에서 사용가능

  • 개별 지역변수 선언 ~ 클래스 선체 선언

가능한한 좁은 범위에 적용해야 함.

  • 변수 선언
  • 아주짧은 메서드
  • 생성자

클래스 전체에 적용할 경우

  • 자칫 심각한 경고를 놓칠 수 있다.

# 한줄이 넘는 메서드/생성자의 @SuppressWarnings

한줄이 넘는 메서드/생성자의 @SuppressWarnings 는 지역 변수 선언 쪽으로 옮긴다

public <T> T[] toArray(T[] a) {
    if (a.length < size) 
        return (T[]) Arrays.copyOf(elements, size, a.getClass());
    System.arraycopy(elements, 0, a, 0, size);
    if (a.length > size)
        a[size] = null;
    return a;
}
1
2
3
4
5
6
7
8

ArrayList 를 컴파일 하면, 다음 경고가 발생한다.

Array.List.java:305: warning: [unchecked] unchecked cast
    return (T[]) Arrays.copyOf(elements, size, a.getClass());
required: T[]
found: Object[]
1
2
3
4

지역 변수를 추가해 @SuppressWarnings 의 범위를 좁힌다.

public <T> T[] toArray(T[] a) {
    if (a.length < size) {
        @SuppressWarnings("unchecked") 
        T[] result = (T[])Arrays.copyOf(elements, size, a.getClass());
        return result;
    }
    // ...
}
1
2
3
4
5
6
7
8