이펙티브 자바 아이템29

한주영·2023년 12월 21일
0

이펙티브자바

목록 보기
21/33

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

Object기반의 스택은 제네릭 타입이 필요

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();
        Object result = elemtns[--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);
    }
}

해당 클래스는 제네릭 타입이어야한다
클라이언트가 스택에서꺼낸 객체를 형본환 -> 런타임 오류가 날 위험이있음

Object를 적절한 타입매개변수로 바꿔보면?

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();
        Object result = elemtns[--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);
    }
}

아이템28에서 설명한것처럼 E와 같은 실체화 불가타입으로배열을 만들수없다

두가지 방법이있다

1)하나는 Object 배열 생성하고 제네릭 배열로 형변환하는 것. 컴파일 경고가 난다.

@SuppressWarnings("unchecked")
public Stack() {
    elements = (E[]) new Object[DEFAULT_INITIAL_CAPACITY];
}

배열 element가 private필드에 저장, 클라이언트에반환되거나 다른메서드에 전달되지 않아서 완전함.

가독성이 더좋음 ->배열타입을 E[]로 선언하여 해당타입의 인스턴스만받음을 어필
형변환을 생성시에만 해주면됨
배열의 런타임 타입이 컴파일 타입과 다르면 힙 오염을 일으킴

elements 필드의 타입을 E[]에서 Object[]로 변경

E는 실체화 불가타입으로 컴파일러는 런타임에 이뤄지는 형변환이 안전할지 증명할 방법이 없음.

//이 배열의 런타임 타입은 E[]가 아닌 Object[]다
public E pop() {
    if (size == 0)
        throw new EmptyStackException();
    
    @SuppressWarnings("unchecked")
    E result = (E) elements[--size];
    
    elements[size] = null; // 다 쓴 참조 해제
    return result;
}

컴파일러가 런타임에 이뤄지는 형변환이 안전한지알수없다
-형변환을 원소를 읽을때마가 해줘야함

제네릭타입안에서 리스트를 사용하는게 항상 가능하지않고
ArrayList도 결국 내부적으로 기본타입 배열을 쓴다
HashMap도 성능을 높일 목적으로 배열을 쓴다.

profile
백엔드개발자가 되고싶은 코린이:)

0개의 댓글