E와 같은 실체화 불가 타입으로는 배열을 만들 수 없다.
배열을 사용하는 코드는 제네릭으로 만들려 할 때는 이 문제가 항상 발목을 잡을 것이다.
적절한 해결책은 두 가지다.
첫 번째는 제네릭 배열 생성을 금지하는 제약을 대놓고 우회하는 방법이다.
Object 배열을 생성한 다음 제네릭 배열로 형병환하는 방법이다.
E[] elements = (E []) new Object[DEFAULT_INITIAL_CAPACITY];
이때 컴파일러는 오류 대신 경고를 내보낼 것이다.
컴파일러는 이 프로그램이 타입 안전한지 증명할 방법이 없지만 우리는 할 수 있다.
따라서 이 비검사 형변환이 프로그램의 타입 안전성을 해치지 않음을 우리 스스로 확인해야 한다.
비검사 형변환이 안전함을 직접 증명했다면 범위를 최소로 좁혀 @SuppressWarnings 애너테이션을 해당 경고를 숨긴다.
제네릭 배열 생성 오류를 해결하는 두 번째 방법은 필드의 타입을 Object[]
로 바꾸는 것이다.
그리고 배열이 반환한 원소를 E로 현변환한다.
E는 실체화 불가 타입이므로 컴파일러는 런타임에 이뤄지는 형변환이 안전한지 증명할 방법이 없다.
그렇기에 이번에도 우리가 직접 증명하고 경고를 숨겨야 한다.
제네릭 배열 생성을 제거하는 두 방법 모두 나름의 지지를 얻고 있다.
첫 번째 방법은 가독성이 더 좋다.
배열의 타입을 E[]
로 선언하여 오직 E 타입 인스턴스만 받음을 확실히 어필한다.
코드도 더 짧다.
보통의 제네릭 클래스라면 코드 이곳저곳에서 이 배열을 자주 사용할 것이다.
그리고 첫 번째 방식에서는 형변환을 배열 생성 시 단 한번만 해주면 되지만, 두 번째 방식에서는 형변환을 배열에서 원소를 읽을 때마다 해줘야 한다.
그렇기에 현업에서는 첫 번째 방식을 더 선호하며 자주 사용한다.