제네릭을 써서 새로 만든 코드가 한번에 깔끔하게 컴파일 되리라는 기대는 버리도록 하자.
제네릭으로 프로그램하다 보면 다음과 같은 많은 컴파일 경고 메시지를 보게 된다.
- 무점검 형변환 경고(unchecked cast warning)
- 무점검 함수 호출 경고(unchecked method invocation warning)
- 무점검 제네릭 배열 생성 경고(unchecked generic array creation warning)
- 무점검 변환 경고(unchecked conversion warning)
모든 무점검 경고는, 가능하면 없애야 한다. 전부 없애고 나면 형 안전성(typesafe)이 보장된다.
제거 할 수 없는 경고 메시지는 형 안전성이 확실할 때만 @SuppressWarnings(“unchecked”) 어노테이션(annotation)을 사용해 억제해야 된다.
아래의 코드는 ArrayList
클래스의 일부이다.
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;
}
ArrayList
클래스를 컴파일해 보면 다음과 같은 경고 메시지가 출력된다.
ArrayList.java:305: warning: [unchecked] unchecked cast
found : Object[], required: T[]
return (T[]) Arrays.copyOf(elements, size, a.getClass());
함수 전체에 SuppressWarnings어노테이션을 붙일수 있으나, 그 보다는 문제가 발생하는 지점에 정확히 붙이는 것이 좋다.
// @SuppressWarnings 정의를 함수 단위에 적용할수 있으나, 적용 범위를 줄이기 위해 지역 변수 사용함
public <T> T[] toArray(T[] a){
if(a.length < size){
/*
아래의 형 변환은 배열의 자료형이 인자로 전달된 자료형인 T[]와 같으므로
형 변환이 정확하므로 @SuppressWarnings("unchecked")처리 함
*/
@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”) 어노테이션을 사용할 때마다, 왜 형 안전성을 위반하지 않는지 주석을 통해 정확히 밝히도록 하자.
무점검 경고(unchecked warning)는 중요하다. 무시하지 말자. 모든 점검 경고는 프로그램 실행 도중에
ClassCastException
이 발생할 가능성을 나타낸다. 그런 경고 메시지는 최선을 다해제거하자. 경고를 제거할수는 없으나, 내가 만든 코드가 형 안전성을 보장한다는 사실을 입증할 수 있다면,@SuppressWarnings("unchecked")
어노테이션을 사용해 해당 경고를 억제하되 어노테이션 적용 범위는 최소화 하자. 그리고, 경고 메시지를 억제한 이유를 주석을 통해 알리자.