아이템 26. 가능하면 제네릭 자료형으로 만들것

26. 가능하면 제네릭 자료형으로 만들것

public class Stack<E>{
    private static final int DEFAULT_INITIAL_CAPACITY = 16;
    private E[] elements;
    private int size = 0;
    
    public Stack(){
        elements = new E[DEFAULT_INITIAL_CAPACITY];
    }
    
    public void push(E e){
        ensureCpapcity();
        elements[size++] = e;
    }
    
    public E pop(){
        if(isEmpty())
            throw new EmptyStackException();
        E result = elements[--size];
        elements[size] = null; // 기존 참조 제거
        return result;
    }
    
    public boolean isEmpty() {
        return 0 == size;
    }
    
    // Stack의 사이즈가 부족해 지면, 원래 크기(size)의 두배로 늘려줌
    private void ensureCapacity(){
        if(elements.length == size)
            elements = Arrays.copyOf(elements, 2 * size + 1);
    }
}

위 클래스의 아래와 같은 오류가 발생한다.

Stack.java:8: generic array creation
    elements = new E[DEFAULT_INITIAL_CAPCITY];
               ^

E는 실체화 불가능 자료형으로 배열을 생성 할 수 없다.

해결 방법은 두 가지가 있다.

  1. 제네릭 배열을 만들수 없다는 조건을 우회 하는 것

배열 객체를 생성할 때, new Object를 통해 배열을 만들어서 제네릭 배열형으로 형변환 시키는 방법으로 관리되는 모든 타입이 E로 보장될 될때 사용 가능하다.

// elements 배열에는 push(E)를 통해 전달된 E 형의 객체만 저장된다.
// 이 정도면 형 안정성은 보장할 수 있지만, 배열의 실행시간 자료형은 E[]가 
// 아니라 항상 Object[] 이다.
@SuppressWarnings("unchecked")
public Stack() {
    elements = (E[]) new Object[DEFAULT_INITIAL_CAPACITY];
}
  1. 배열의 자료형을 E[]에서 Object[]로 바꾸는 것
private Object[] elements;
...
public Stack() {
    elements = (E[]) new Object[DEFAULT_INITIAL_CAPACITY];
}
...
// 무점검 경고를 적절히 억제한 사례
public E pop() {
    if (size = 0)
        throw new EmptyStackException();
    // 자료형이 E인 원소만 push하므로, 아래의 형변환은 안전하다.
    @SuppressWarnings("unchecked") 
    E result = elements[--size];
    
    elements[size] = null;  // 기존 참조 제거
    return result;
}

제네릭 배열 해결책 정리

  1. 무점검 형변환(unchecked cast) 경고 억제의 위험성은 스칼라(scala) 자료형 보다 배열 자료형이 더 크기 때문에, 두번째 해법이 더 낫다고 볼 수 있다.

  2. 현실적으로 E배열을 사용하는 코드가 이곳 저것에 흩어져 있다면, 배열 생성 시 첫번째 방법으로는 E[]으로 한번만 형변환을 하면되지만, 두번째 방법으로는 코드 여기저기에서 E로 형변환을 해야하므로 첫번째 방법이 더 낫다

규칙 26. 가능하면 제네릭 자료형으로 만들것 (173.p)를 다시 한번 꼭 읽어 볼것!!!