제네릭을 사용하면
과 같은 경고를 마주칠 수 있다. 대부분은 컴파일러가 알려준대로 처리하면 더 이상 해당 경고는 나타나지 않는다. 즉, 런타임에 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 에너테이션을 사용한다면 반드시 왜 사용했는지에 대한 주석을 달아두도록 하자! 그 이유는 어쨋든 본인의 판단으로 비검사 경고를 무시했기 때문에 이에 대한 이유를 작섬함으로써 코드의 가독성과 안정성을 높일 수 있다.