본문 바로가기

개발/[스터디] 이펙티브 자바

[이펙티브자바]아이템26. 로타입은 사용하지 말라

제네릭(Generic)이란? (사전적 의미)

- generic은 직역하면 '포괄적인. 일반적인' 의미이다.

 

제네릭(Generic)이란? (프로그래밍에서의 의미)

- 하나의 자료구조에서 여러가지 타입을 지원하기 위해 탄생

- 특정 타입을 미리 지정해주는 것이 아니라, 사용자가 필요한 타입을 지정하도록 하는 것

// 같은 ArrayList인데 타입만 다르다. 하나의 자료 구조로 통일할 수는 없을까?
ArrayList<Integer> list1 = new ArrayList<Integer>();
ArrayList<String> list2 = new ArrayList<String>();

 

제네릭타입(Generic Type)

제네릭 클래스, 제네릭 인터페이스를 통틀어 일컫는 말.

 

제네릭 클래스, 제네릭 인터페이스

- 클래스, 인터페이스 선언에 타입 매개변수가 쓰일 경우.

- 아래 예제에서 Book<T> 처럼 '클래스명(혹은 인터페이스명) + <T> '의 형태를 매개변수화타입(=Parameterized Type)이라 부른다.

public class Book<T> {
	private T t;
    
    public T get() {
    	return t;
    }
    
    public void set(T t) {
    	this.t = t;
    }
}

 

로타입(raw type)

제네릭 타입에서 타입 매개변수를 전혀 사용하지 않았을 경우 

예. List<E>에서 로타입은 List이다.

 

로타입의 문제점

아래 예제를 보자. Stamp 인스턴스만 넣으라고 주석을 했지만, 실수로 Coin을 넣었다. 하지만 컴파일 타임에 실수를 알 수 없다.

// Stamp 인스턴스만 넣을 것!
private final Collection stamps = ...;

stamps.add(new Coin(...));

Stamp stamp = (Stamp) stamps.get(0); // classCastException 내뿜는다.

위 코드는 제네릭을 사용하여 안정성을 확보할 수 있다. 

private final Collection<Stamp> stamps = ...;

 

와일드타입: 제네릭타입을 사용하고 싶지만, 실제 타입 매개변수가 무엇인지 알고 싶지 않을 때 사용하자.

static int numElementsInCommon(Set<?> s1, Set<?> s2) { ... }

 

결론

로타입은 런타임에 예외를 발생시킬 여지가 있으므로 사용하지 말자. 로타입은 제네릭 도입 이전 코드와의 호환성을 위해 제공될 뿐이다. 

예를 들어, set<Object>나 set<?>은 안전하지만, 로타입인 set은 안전하지 않으므로 사용하지 말자.