본문 바로가기

STUDY/이펙티브자바

5-4) 이왕이면 제네릭 타입으로 만들라

Object 기반 Stack

 

public class Stack {
    private Object[] elements;
    private int size = 0;
    private static final int DEFAULT_INITIAL_CAPACITY = 16;
	
    public Stack() {
        this.elements = new Object[DEFAULT_INITIAL_CAPACITY];
    }
	
    public void push(Object e) {
        this.ensureCapacity();
        this.elements[this.size++] = e;
    }
	
    public Object pop() {
        if(this.size == 0) {
            throw new EmptyStackException();
        }
        Object result = this.elements[--this.size];
        this.elements[this.size] = null;
        return result;
    }
	
    public boolean isEmpty() {
        return this.size == 0;
    }
	
    private void ensureCapacity() {
        if(this.elements.length == size) {
            this.elements = Arrays.copyOf(this.elements, this.size * 2 + 1);
        }
    }
}

위의 코드는 객체를 저장하고 뽑아내는 Stack 클래스를 Object 타입을 활용하여 만든 예제이다. 이 Stack 클래스는 에러없이 동작하지만, 사용하는 측면에서는 불편함이 많다. 같은 타입의 객체를 보관하고 꺼내는 것이 일반적인데 pop() 메소드의 반환형이 Object라서 사용할때마다 형변환을 해주어야 한다. 그리고 이는 사용하기에 불편할 뿐만 아니라 형변환이 잘못될 경우 런타임 에러가 발생할 수 있다.

 

// pop() 메소드를 호출할 때마다 형변환을 해주어야 한다.
Stack strStack = new Stack();
strStack.push("hello");
strStack.push("world");
String str = (String)strStack.pop();

 

 


제네릭을 사용한 Stack

 

public class Stack<T> {
    private T[] elements;
    private int size = 0;
    private static final int DEFAULT_INITIAL_CAPACITY = 16;

    // elements는 클래스 내부에서만 사용하고,
    // elements에 값을 넣을때와 꺼낼때 모두 T 타입을 사용하므로 안전한 코드이다.
    @SuppressWarnings("unchecked")
    public Stack() {
        this.elements = (T[]) new Object[DEFAULT_INITIAL_CAPACITY];
    }
	
    public void push(T e) {
        this.ensureCapacity();
        this.elements[this.size++] = e;
    }
	
    public T pop() {
        if(this.size == 0) {
            throw new EmptyStackException();
        }
        T result = this.elements[--this.size];
        this.elements[this.size] = null;
        return result;
    }
	
    public boolean isEmpty() {
        return this.size == 0;
    }
	
    private void ensureCapacity() {
        if(this.elements.length == size) {
            this.elements = Arrays.copyOf(this.elements, this.size * 2 + 1);
        }
    }
}

위의 코드는 제네릭을 활용하여 만든 Stack 클래스이다. 선언할 때 보관할 타입을 타입 매개변수<T>로 받아서 push()와 pop() 메소드에 해당 타입으로 객체를 전달받고 반환한다. 덕분에 이후에 Stack 클래스를 사용할 때는 형변환이 필요없다.

 

// Stack에 저장할 타입 매개변수를 넘겨주면 이후에 형변환 없이 사용할 수 있다.
Stack<String> strStack = new Stack<>();
strStack.push("hello");
strStack.push("world");
String str = strStack.pop();

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

728x90