제네릭에 대한 설명을 하기 위해
6장에서 사용했던 스택 코드를 사용할 것입니다.
public class Stack {
private Object[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;
public Stack() {
elements = new Object[DEFAULT_INITIAL_CAPACITY];
}
public void push(Object e) {
ensureCapacity();
elements[size++] = e;
}
public Object pop() {
if (size == 0)
throw new EmptyStackException();
return elements[--size];
}
private void ensureCapacity() {
if (elements.length == size)
elements = Arrays.copyOf(elements, 2 * size + 1);
}
}
흔한 스택입니다.
보시면 pop의 리턴타입이 Object입니다.
때문에 사용하는 측에서 형변환을 해주어야합니다.
형안정성에 문제가 생길 확률이 높습니다.
때문에 이 코드를 제네릭 처리하겠습니다.
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 result;
}
private void ensureCapacity() {
if (elements.length == size)
elements = Arrays.copyOf(elements, 2 * size + 1);
}
}
Stack 자체에 제네릭을 주고 있기 때문에 컴파일 단계에서 형 체크를 합니다.
런타임에서 에러가 나지 않겠죠
하지만
이 부분에서 에러가 납니다.
E같은 실체화 불가능 자료형으로는 배열을 생성할 수 없습니다.
25에서도 설명했지만, 배열은 런타임시 자료형의 정보를 필요로 합니다.
하지만 E로 처리해 두면 런타임 단계에 들어갔을 때
어떤 자료형인지 런타임 단계에서는 정보가 없게 됩니다.
때문에 직접 초기화가 안되게 컴파일러가 잡아줍니다.
고치는 방법은
이러한 방법이 있습니다.
하지만 컴파일러가 점검 작업을 진행하지 않았다고, 형 안정성에 문제가 일어날 수 있음을 경고를 줍니다.
하지만 프로그래머는 이 경고가 별 문제가 없음을 금방 알 수 있습니다.
스택의 배열 자체는 리턴되지도 않고, 타입은 전부 하나로 통일되니까요.
따로 점검 작업이 필요하지 않습니다.
그럴 땐 이전에 배웠던 @SuppressWarnings 어노테이션으로 눌러버립시다.
문제가 없음을 확신할 수 있으니 사용할 수 있는 방법입니다.
다른 방법도 있습니다.
처음부터 element를 Object 배열로 만드는 방법입니다.
그러면 당연히 pop 메소드에서 형변환 오류가 나게 됩니다.
(E) 로 형변환을 해주면 이번엔 경고가 발생합니다
형을 체크하지 않았다는 표시죠.
위와 마찬가지로 별 의미 없는 경고이기에 무시해줍시다.
@SuppressWarnings("unchecked")
public E pop() {
if (size == 0)
throw new EmptyStackException();
E result = (E) elements[--size];
elements[size] = null;
return result;
}
이렇게 하면 에러가 사라집니다.
그렇다면 어떤 방법이 좋을까요?
취향차이이지만,
위의 코드처럼 항상 배열을 사용하는 코드가 하나라고 가정할 수 없습니다.
두번째 방법은 매열을 사용하는 코드 별로 작업을 해주어야하기 때문에
첫번째 방법이 조금 더 보편적으로 사용되는 편입니다.
'프로그래밍 > Java' 카테고리의 다른 글
이펙티브 자바 규칙 25 - 배열 대신 리스트를 써라 (0) | 2018.03.22 |
---|---|
이펙티브 자바 규칙 24 - 무점검 경고를 제거하라 (0) | 2018.03.09 |
이펙티브 자바 규칙 23 - 새 코드에는 무이자 제네릭 자료형을 사용하지 마라 (0) | 2018.03.08 |