Skip to content

Latest commit

 

History

History
95 lines (71 loc) · 3.04 KB

29. 이왕이면 제네릭 타입으로 만들라.md

File metadata and controls

95 lines (71 loc) · 3.04 KB

이왕이면 제네릭 타입으로 만들라

Object 기반 스택에서 제네릭 스택으로 변경하기

public class Stack {
    private Object[] elements;
    private int size = 0;
    private static final int DEFAULT_INITIAL_CAPACITY = 16;
    
    pulic 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();
        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);
    }
}
  1. 클래스 선언에 타입 매개 변수를 추가한다.

    • 타입 매개 변수의 이름은 보통 E를 사용한다.
    public class Stack<E> {
        private E[] elements;
        private int size = 0;
        private static final int DEFAULT_INITIAL_CAPACITY = 16;
        
        pulic 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);
        }
    }
    • E실체화 불가 타입이기 때문에 배열을 만들 수 없다.
      • 해결책 1) 제네릭 배열 생성 금지 제약 우회
        • Object 배열을 생성한 후 제네릭 배열로 형변환
          • 컴파일러 오류가 발생하진 않지만 경고가 발생하고, 일반적으로 안전하지 않다.
        • 비검사 형변환이 안전함을 증명했다면 최소 범위에서 @Suppress Warning 어노테이션으로 해당 경고를 숨기자.
        • 명시적으로 형변환하지 않아도 ClassCasatException 걱정 없이 사용할 수 있게 된다.
        • 코드가 짧고, 가독성이 좋다는 장점을 가지고 있지만, 배열의 런타임 타입과 컴파일타임 타입이 다르기 때문에 힘 오염을 일으킬 수 있다.
      • 해결책 2) elements 필드의 타입을 E[]가 아닌 Object[]로 사용
        • E가 실체화 불가 타입이기 떄문에 런타임에 이루어지는 형변환이 안전한지 증명할 수 없다. (경고 발생)
          • 안전함을 증명하고, 경고를 숨기자.

정리

  • 새로운 타입을 설계할 때는 형변환 없이도 사용할 수 있도록 제네릭 타입을 사용하자!