맞는데 왜 틀릴까..?

Java/Effective Java

[Effective Java] Item 27. 비검사 경고를 제거하라

안도일 2023. 5. 9. 17:28

제네릭을 사용하면 수많은 비검사 경고를 볼 수 있다.

대부분의 비검사 경고는 쉽게 제거할 수 있지만 제거하기 어려운 경고도 있다.

 

모든 비검사 경고를 제거한다면 그 코드는 타입 안전성이 보장된다.

 

@SuppressWarnings("unchecked")

 

경고를 제거할 수는 없지만 타입 안전하다고 확신한다면 해당 애너테이션을 달아 경고를 숨기자.

 

  • 안전하다고 검증된 비검사 경고를 숨기지 않고 그대로 두면 진짜 문제를 알리는 새로운 경고가 파묻혀 눈치채기 힘들다.
  • 가능한 한 좁은 범위에 적용하자.
  • 한 줄이 넘는 메서드나 생성자에 달린 에너테이션은 지역변수 선언으로 옮기자.

 

 

애너테이션은 선언에만 달 수 있기 때문에 return 문에 달 수 없다.

 

 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;
 }

 

위 코드에서 오류는 발생하지 않지만, 타입 안전 경고가 발생할 수 있다.

이 메서드는 제네릭 메서드로 배열 요소의 타입을 T로 추론하는데, 자바에서 제네릭 배열을 생성하는것은 타입 안전성을 해칠 우려가 있어 안전하지 않다고 판단한다.

 

 

반환값을 담은 지역변수를 선언하고 애너테이션 달기

 

public <T> T[] toArray(T[] a) {
        if (a.length < size){
            @java.lang.SuppressWarnings("unchecked") T[] result = 
                    (T[]) Arrays.copyOf(elements, size, a.getClass());
            return result;

    }
        System.arraycopy(elements, 0, a, 0, size);
        if(a.length>size)
            a[size]=null;
        return a;
}

 

메서드 전체에 에너테이션을 달면 범위가 필요 이상으로 넓어져 자칫 심각한 경고를 놓칠 수 있다.

 


 

만약 비검사 경고를 없앨 방법을 찾지 못했다면 코드가 안전함을 증명하고 가능한 범위를 좁혀 애너테이션으로 숨기자.

 

  • 비검사 경고는 중요하니 무시하지 말자.
  • 비검사 경고는 최선을 다해 제거하자.
  • 비검사 경고를 숨기는 범위를 최소한으로 줄이자.
  • @SuppressWarnings("unchecked") 애너테이션을 사용할 때는 그 경고를 무시해도 안전한 이유를 주석으로 남기자.