본문 바로가기
Java/Effective Java 3E

[이펙티브자바 3판] ITEM29. 이왕이면 제네릭 타입으로 만들어라

by 잭피 2020. 10. 15.

이번장의 핵심은...

클라이언트에서 직접 형 변환해야 하는 타입보다 제네릭 타입이 더 안전하고 쓰기 편하다

그러니 새로운 타입을 설계할 때는 형 변환 없이도 사용할 수 있도록 하라

기존 타입 중 제네릭이었어야 하는 게 있다면 제네릭 타입으로 변경하자

기존 클라이언트에는 아무 영향을 주지 않으면서, 새로운 사용자를 훨씬 편하게 해주는 길이다


제네릭 타입으로 만들자

제네릭 타입을 새로 만드는 일은 조금 어렵지만 배워두면 그만한 값어치를 충분히 한다

// 제네릭이 절실한 강력 후보! (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 = 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. 클래스 선언에 타입 매개변수를 추가

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

→ E와 같은 실체화 불가 타입으로는 배열을 만들 수 없으므로 오류

해결책 1 : 제네릭 배열 생성을 금지하는 제약을 대놓고 우회하는 방법

Object 배열을 생성한 다음 제네릭 배열로 형 변환 (컴파일러는 오류 대신 경고)

→ 직접 안전함을 증명했다면 범위를 최소로 좁혀 @SuppressWarnings 애너테이션으로 해당 경로를 숨긴다

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

 

해결책 2 : elemnets 필드의 타입을 E[] → Object []로 바꾼다

private Object[] elements;

// 비검사 경고를 적절히 숨긴다
public E pop() {
	if(size==0){
		throw new EmptyStackException();
	}
	// push에서 E 타입만 허용하므로 이 형변환은 안전하다
	@SuppressWarnings("unchecked")
	E result = (E) elements[--size];
	elements[size] = null;
	return result;
}

제네릭 배열 생성을 제거하는 2가지 방법 모두 지지를 얻고 있다

 

1번은 가독성이 더 좋음 - 배열의 타입을 E[]로 선언하여 오직 E타입 인스턴스만 받음을 확실히 어필

1번은 형변환을 배열 생성 시 단 한 번만, 2번은 배열에서 원소를 읽을 때마다 해줘야 한다

현업에서는 1번을 선호, heap pollution이 맘에 걸리는 프로그래머는 2번을 선호

(이번 예제에서는 heap pollution이 일어나지 않음)

 

 

 

이 글은 “이펙티브 자바 3판” 책 내용을 정리한 글입니다.

만약 저작권 관련 문제가 있다면 “shk3029@kakao.com”로 메일을 보내주시면, 바로 삭제하도록 하겠습니다.

 

댓글