배열을 제네릭으로 바꾸기
배열을 제네릭으로 바꾸는 과정에서 마주칠 수 있는 에러는 다음과 같다.
Stack.java8: generic array creation
elements = new E[DEFAULT_INITIAL_CAPACITY];
이 에러는 E와 같은 실체화 불가 타입으로는 배열을 만들 수 없기 대문에 발생한다. 이를 위한 해결책은 다음과 같다.
- Object 배열로 생성하고 제네릭 배열로 형변환 하는 방법 - 컴파일러는 오류 대신 경고를 보여주지만, 일반적으로 타입 안전하지 않다.
elements = (E[]) new Object[DEFAULT_INITIAL_CAPACITY];
이 방법은 형변환을 배열 생성시 한 번만 하지만, 힙 오염의 단점이 있다.
- E[]에서 Object[]로 바꾼다. - 컴파일러는 런타임에 이뤄지는 형변환이 안전하지 증명할 수 없기에 경고를 보낸다.
E result = elements[--size];
이 방법은 힙 오염을 시키지는 않지만, 배열에 접근할 때마다 형변환을 하는 단점이 있다.
한정적 타입 매개변수
E를 사용하게 되면 모든 타입을 받을 수 있다. 만약 타입을 한정시키고 싶다면 한정적 타입 매개변수를 이용해야 한다.
// Number 클래스 또는 상속한 클래스로 제한된다.
public class Stack<E extends Number> {
private E[] elements;
public Stack() {
elements = (E[]) new Object[DEFAULT_INITIAL_CAPACITY];
}
}
이렇게 타입을 한정하게 되면 이전에 잘 동작하던 코드가 동작하지 않을 수 있다. 이런 경우에는 두 번째 방법을 쓸 수 있다.
public class Stack<E extends Number> {
private Number[] elements;
public Stack() {
elements = new Number[DEFAULT_INITIAL_CAPACITY];
}
// 꺼내쓸 때 형변환해서 쓴다.
public E pop() {
E result = (E) elements[--size];
}
}