Skip to content

item 29 JungHyunLyoo

JungHyunLyoo edited this page Apr 10, 2020 · 3 revisions

일반 클래스를 제네릭 클래스로 만들기

  1. 클래스 선언에 <정규 타입 매개변수>를 추가하기(보통 E 사용)
  2. 클래스 내의 제네릭으로 지정하고 싶은 필드 타입을 클래스 선언에 추가해놓은 <정규 타입 매개변수>로 바꾸기

제네릭을 적용한 Stack

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;
    }

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

    private void ensureCapacity() {
        if (elements.length == size)
            elements = Arrays.copyOf(elements, 2 * size + 1);
    }

    public static void main(String[] args) {
        Stack<String> stack = new Stack<>();
        for (String arg : args)
            stack.push(arg);
        while (!stack.isEmpty())
            System.out.println(stack.pop().toUpperCase());
    }
}

하지만 위 코드는 컴파일되지 않는다!! E와 같은 실체화 불가 타입으로는 배열을 만들 수 없기 때문이다.

해결 방법 1

1. 생성자 내에서 elements 필드의 인스턴스 생성을 아래와 같이 수정

elements = new E[DEFAULT_INITIAL_CAPACITY];
-> elements = (E[]) new Object[DEFAULT_INITIAL_CAPACITY];


2. 생성자에 @SuppressWarnings("unchecked") 어노테이션을 추가


장점 : 가독성 ↑
단점 : 배열의 런타임 타입이 컴파일타임 타입과 달라 힙 오염(item 32) ↑

해결 방법 2

1. elements필드의 타입을 E[] -> Object[]로 교체
그리고 역시 E가 실체화 불가 타입이기 때문에, elements 타입 내 원소를 얻어오는 부분 수정

E result = elements[--size];
-> E result = (E) elements[--size];


2. @SuppressWarnings("unchecked") 어노테이션을 수정한 코드 바로 위에 추가


장점 : 힙 오염 ↓
단점 : 가독성 ↓
Clone this wiki locally