본문 바로가기
JAVA/Effective Java

item 27. 비검사 경고를 제거하라

by Garonguri 2022. 5. 10.
728x90

 

비검사 경고를 제거한 코드는 타입 안정성이 보장된다.


비검사 경고?

제네릭을 사용하기 시작했을 때 볼 수 있는 수많은 컴파일러 경고이다.

warning : [unchecked]로 시작하며, casting 할 때 검사를 하지 않았다고 뜨는 경고라고 할 수 있다.

 

비검사 경고를 모두 제거하면 타입 안정성이 보장되기 때문에, 런타임에 ClassCastException이 발생하는 것을 막아줄 수 있다.

비검사 경고를 확인하기 위해서는 컴파일러에 -Xlint:unchecked 옵션을 주면 된다.


[ 비검사 경고 제거 시 유의 사항 ]

 

1. 경고를 제거할 수는 없으나 타입 안전하다고 확신할 수 있다면, @SuppressWarnings("unchecked") 애너테이션을 추가한다.

- 경고를 숨겨주는 역할을 한다.

- 타입 안정성을 반드시 검증해야 한다. 

      - 검증 없이 경고를 숨기는 경우, 런타임에 ClassCastException이 발생한다.

      - 검증을 했으나 경고를 숨기지 않는 경우, 기존의 영향을 주지 않는 경고에 새롭게 생긴 프로그램에 영향을 줄 수 있는  경고가 가려져             알아챌 수 없는 상황이 생길 수 있다.

- 해당 경고를 무시해도 안전한 이유는 항상 주석으로 남겨야 한다.

 

2. @SuppressWarnings 애너테이션은 가능한 한 좁은 범위에 적용해야 한다.

//SuppressWarnings.java
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
//범위가 매우 넓다. 어떤 선언에도 달 수 있다.
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
    String[] value();
}

- 보통 변수 선언, 짧은 메서드, 생성자 범위에서 적용된다.

- 심각한 경고를 놓칠 수도 있기 때문에 클래스 단위에서는 사용하지 않는다.

 

3. 긴 메서드나 생성자에 @SuppressWarnings 애너테이션이 있다면, (지역변수를 추가해) 지역변수선언 쪽으로 옮겨야 한다.

//ArrayList.java
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
    checkForComodification();
    if (a.length < size)
        return (T[]) Arrays.copyOfRange(
                root.elementData, offset, offset + size, a.getClass());
    System.arraycopy(root.elementData, offset, a, 0, size);
    if (a.length > size)
        a[size] = null;
    return a;
}
public class item27 {

    transient Object[] elementData; // non-private to simplify nested class access
    private int size;

    public <T> T[] toArray(T[] a) {
        if (a.length < size) {
            // Make a new array of a's runtime type, but my contents:
            // 지역변수 result를 만들어 해당 변수에 애너테이션을 달아주었다.
            @SuppressWarnings("unchecked") 
            T[] result = (T[]) Arrays.copyOf(elementData, size, a.getClass());
            return result;
        }
        System.arraycopy(elementData, 0, a, 0, size);
        if (a.length > size)
            a[size] = null;
        return a;
    }
}

 

728x90

댓글