이펙티브 자바 #item 27 비검사 경고를 제거하라

임현규·2023년 1월 31일
0

이펙티브 자바

목록 보기
27/47
post-thumbnail

제네릭 사용시 나타나는 비검사 경고를 제거하자

제네릭을 사용하면

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

과 같은 경고를 마주칠 수 있다. 대부분은 컴파일러가 알려준대로 처리하면 더 이상 해당 경고는 나타나지 않는다. 즉, 런타임에 ClassCastException 이 발생할 일이 없어지고, 의도한대로 동작하리라 확신할 수 있게 된다.

비검사 경고 제거가 어려운 경우

타입 캐스팅에 문제가 없고 타입 안정성을 확실히 보장하지만 비검사 경고 제거가 어려운 상황이 발생할 수 있다. 이런 경우 @SuppressWarnings 에너테이션을 활용해 비검사 경고를 무시하는 방법이 있다.

다만, 이러한 방법은 타입 안정성을 확신할 때만 사용해야 한다. 또한 매우 국소적으로 사용해야 한다. 그 이유는 말 그대로 비검사 경고를 무시하는 것이기 때문에 넓은 범위에 적용하면 나중에 확신했다고 생각하는 타입에 문제가 생기면, 찾기가 어렵기 때문이다.

// 잘못된 에너테이션 사용 예
@SuppressWarnings("unchecked")
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;
}

return에 바로 에너테이션을 달 수 없다. 해당 에너테이션은 선언문에만 달 수 있는데 국소적으로 처리하려고 해도 할 수가 없으므로 메서드에 달았다. 그러나 이는 문제가 발생할 지역 외에 메서드 블록 내 모든 부분에 비검사 경고 무시를 했으므로 적절치 않다.

// 필요한 부분에 적절히 적용한 예
public <T> T[] toArray(T[] a) {
	if (a.length < size) {
    	// 생성한 배열과 매개변수로 받은 배열의 타입이 모두 T[]로 같으므로
        // 옳바른 형변환이다.
    	@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;
}

조금 번거롭긴 해도 result 변수를 선언해서 에너테이션을 달아준다. 이러면 에너테이션에 의도대로 result에 잘 마킹되어 있음을 알 수 있다. 코드를 봤을 때 어떤 의도로.. 어떤 부분의 코드의 비검사 경고를 제거하려 했는지 파악하는 데 메서드에 지정한 것보다 훨씬 쉽게 파악할 수 있다.

그리고 @SuppressWarnigs 에너테이션을 사용한다면 반드시 왜 사용했는지에 대한 주석을 달아두도록 하자! 그 이유는 어쨋든 본인의 판단으로 비검사 경고를 무시했기 때문에 이에 대한 이유를 작섬함으로써 코드의 가독성과 안정성을 높일 수 있다.

profile
엘 프사이 콩그루

0개의 댓글