배열은 공변이지만 제네릭은 불공변이다
Object[] objectArray = new Long[1];
objectArray[0] = "문자열 삽입하기";
JavaScript
복사
•
위 경우는 자바 문법상 허용되는 코드로, 실행 시키면 ArrayStoreException이 발생한다.
List<Object> ol = new ArrayList<Long>();
ol.add("문자열 삽입하기");
JavaScript
복사
•
하지만 위 예시는 문법에 맞지 않아 컴파일 시 오류를 발생시킨다.
•
또한 배열은 런타임 중에 자신이 담기로 한 원소의 타입을 인지하고 있기 때문에 실체화(reify)가 가능해 위 상황에서 ArrayStoreException을 발생시킬 수 있다.
•
하지만 제너릭은 타입 정보가 컴파일 시에만 검사하고, 런타임에는 소거 되어 알 수 없다.
배열과 제네릭은 잘 어우러지지 못한다
•
배열은 제네릭 타입, 매개변수화 타입, 타입 매개변수로 사용할 수없다.(new List<E>[], new List<String>[], new E[]와 같은 식으로 생성할 수 없다)
•
이렇게 제네릭 배열 생성을 하지 못하도록 한 이유는 컴파일러가 자동 생성한 형변환 코드에서 런타임 중에 ClassStoreException이 발생할 수 있기 때문에 타입 안전하지 않기 때문이다.
•
배열로 형변환할 때 제네릭 배열 생성 오류나 비검사 형변환 경고가 뜨는 경우 E[] 배열 대신 List<E>를 사용하면 해결되고, 그로인해 성능이 약간 나빠지지만 타입 안정성과 상호운용성이 좋아진다.
제네릭은 실체화 불가 타입이다
•
E, List<E>, List<String>과 같은 타입들을 실체화 불가 타입(non-reifiable type)이라 하는데, 실체화되지 않아 런타임에는 컴파일 시보다 타입 정보를 적게 가지는 타입을 말한다.
•
실체화 될 수 있는 타입은 List<?>나 Map<?, ?>와 같은 비한정적 와일드카드타입 뿐이다.