public class Stack<E> {
private E[] elements; // <---
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;
public Stack() {
elements = new E[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 resuilt;
}
// 이하 생략
}
실체화 불가 타입으로 인해 오류 발생(#28)
해결책 1 - 우회하기
코드 29-3 배열을 사용한 코드를 제네릭으로 만드는 방법 1
@SuppressWarnings("unchecked")
public Stack() {
elements = (E[]) new Object[DEFAULT_INITIAL_CAPACITY];
}
장점
가독성이 좋다. 코드 간결
단점
컴파일타임의 타입과 런타임의 타입이 달라져서 힙 오염(#32)을 일으킴
해결책 2 -필드 타입 변경
private Object[] elements;
29-4 배열을 사용한 코드를 제네릭으로 만드는 방법 2
public E pop() {
if (size == 0)
throw new EmptyStackException();
// push에서 E 타입만 허용하므로 이 형변환은 안전하다
@SuppressWarnings("unchecked") E result = (E) elements[--size]; // <---
elements[size] = null; // 다쓴 참조 해제
return resuilt;
}
장점
단점
원소를 읽을 때마다 처리해줘야 함
정리
위의 예시는 배열보다는 리스트를 우선하라(#28) 것과 모순되는 듯함
제네릭의 근본 문제인 박싱된 기본 타입(#61)만 사용할 수 있음
한정적 타입 매개변수(bounded type parameter) 사용 가능
class DelayQueue<E extends Delayed> implements BlockingQueue<E>
개요
사용하기
타입 매개변수 추가
코드 29-2 제네릭 스택으로 가는 첫 단계 - 컴파일되지 않는다.
해결책 1 - 우회하기
코드 29-3 배열을 사용한 코드를 제네릭으로 만드는 방법 1
해결책 2 -필드 타입 변경
29-4 배열을 사용한 코드를 제네릭으로 만드는 방법 2
정리