[Effective Java] 아이템29 - 이왕이면 제너릭 타입으로 만들라

Stack 클래스를 <E> Type을 받아서 제네릭 스택으로 만드는 과정에서 생기는 컴파일 에러와 Unchecked Exception을 살펴본다. (보통 형변환 런타임 오류 때문에 제네릭을 사용한다고 생각하면 될 것 같다.)

클라이언트에서 직접 형변환을 안해도 되게끔 제네릭 타입으로 만들자.

  private E[] elements;
  elements = new E[DEFAULT_INITIAL_CAPACITY];

위와 같은 코드를 짰을때, 아래와 같은 컴파일 에러가 발생한다.

Stack,java:8: generic array creation
elements = new E[DEFAULT_INITIAL_CAPACITY];

아이템28에서 설명한 것처럼, E는 실체화가 불가하기 때문에 배열로 만들 수 없다.

1. Object 배열을 생성한 뒤 제네릭 배열로 형변환

  elements = (E[]) new Object[DEFAULT_INITIAL_CAPACITY];

이렇게 하면 컴파일러는 오류 대신 경고를 내보낸다.

Stack.java:8: warning: [unchecked] unchecked cast found: Object[], required: E[]
elements = (E[]) new Object[DEFAULT_INITIAL_CAPACITY];

E 타입이 안전하지 않다는 것이다. 하지만 개발자가 타입 안전성을 해치지 않음을 확인했을 경우에는 @SuppressWarnings 어노테이션으로 해당 경고를 숨기면 된다.

@SuppressWarnings("unchecked")
public Stack() {
elements = (E[]) new Object[DEFAULT_INITIAL_CAPACITY];
}

이 때, 배열의 런타임 타입(E[])가 컴파일타임(Object[])와 달라서 heap pollution을 일으킨다. (아이템32)

2. elements 필드의 타입을 E[]에서 Object[] 로 변경한다.

Stack.java:19: incompatible types found: Object, required: E
E result = elements[—size];

Object[] 배열인 elements에서 원소를 꺼낼 때 형변환 Unchecked Exception이 있는 것이다. 타입 안전한지 보장이 된다면 이 또한 SuppressWarnings를 추가해주면 된다.

@SuppressWarnings("unchecked") E result = (E) elements[size];

댓글남기기