아이템 29. 이왕이면 제네릭 타입으로 만들라 - KwangtaekJung/book-effective-java GitHub Wiki

  • Object 기반 스택
    • Object[]을 사용
public class StackByObjectArray {
    private Object[] elements;
    private int size = 0;
    private static final int DEFAULT_INITIAL_CAPACITY = 16;

    public StackByObjectArray() {
        elements = new Object[DEFAULT_INITIAL_CAPACITY];
    }

    public void push(Object e) {
        ensureCapacity();
        elements[size++] = e;
    }

    public Object pop() {
        if (size == 0) {
            throw new EmptyStackException();
        }

        Object result = elements[--size];
        elements[size] = null;
        return result;
    }

    public boolean isEmpty() {
        return size == 0;
    }

    private void ensureCapacity() {
        if (elements.length == size) {
            elements = Arrays.copyOf(elements, 2 * size + 1);
        }
    }
}
  • Generic 기반 스택
    • 타입 파라미터 사용하여 Generic로 만들고 Generic 내부의 elements 변수는 배열 사용
      • 방법1)
        • Object 배열 생성 후 제네릭 배열로 형변환하는 방식으로 generic array creation 해결한다.
        • 비검사 형변환 안정성 직접 점검 후 @SupressWarnings 사용하여 경고 숨김.
public class StackByGeneric1<E> {
    private E[] elements;
    private int size = 0;
    private static final int DEFAULT_INITIAL_CAPACITY = 16;

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

    public void push(E e) {
        ensureCapacity();
        elements[size++] = e;
    }

    public E pop() {
        if (size == 0) {
            throw new EmptyStackException();
        }

        E result = elements[--size];
        elements[size] = null;
        return result;
    }

    public boolean isEmpty() {
        return size == 0;
    }

    private void ensureCapacity() {
        if (elements.length == size) {
            elements = Arrays.copyOf(elements, 2 * size + 1);
        }
    }
}
- 방법2) 
  - 아예 elements 필드의 타입을 Object[]로 변경한다. (애초에 generic array creation 발생하지 않음.)
  - pop 시 E로 형변환하고 비검사 경고 제거한다.
public class StackByGeneric2<E> {
    private Object[] elements;
    private int size = 0;
    private static final int DEFAULT_INITIAL_CAPACITY = 16;

    public StackByGeneric2() {
        elements = new Object[DEFAULT_INITIAL_CAPACITY];
    }

    public void push(E e) {
        ensureCapacity();
        elements[size++] = e;
    }

    public E pop() {
        if (size == 0) {
            throw new EmptyStackException();
        }

        @SuppressWarnings("unchecked")
        E result = (E) elements[--size];
        elements[size] = null;
        return result;
    }

    public boolean isEmpty() {
        return size == 0;
    }

    private void ensureCapacity() {
        if (elements.length == size) {
            elements = Arrays.copyOf(elements, 2 * size + 1);
        }
    }
}
  • 배열보다는 리스트를 우선하라과 모순된다 ???
    • 제네릭 타입 안에서 리스트를 사용하는 것이 항상 가능하지 않고, 꼭 더 좋은 것도 아니다.
    • 성능 향상을 위해 List보다 배열을 사용해야 하는 경우도 있다.