<aside> <img src="/icons/help-alternate_gray.svg" alt="/icons/help-alternate_gray.svg" width="40px" />

제네릭(generic)은 자바 5부터 사용할 수 있다. 제네릭을 지원하기 전에는 컬렉션에서 객체를 꺼낼 때마다 형변환을 해야 했다. 형변환 오류가 나곤 했는데, 제네릭을 사용하면 컬렉션이 담을 수 있는 타입을 컴파일러에 알려주게 된다. 그래서 더 안전하고 명확한 프로그램을 만들 수 있게 되었다. 이러한 이점을 최대로 살리고 단점을 최소화하는 방법을 알아보자.

</aside>

26] 로 타입(raw type)은 사용하지 말라.

- raw type이란?

로 타입은 제네릭(Generic) 타입에서 타입 매개변수를 전혀 사용하지 않은 때를 말합니다. 반대로 클래스와 인터페이스 선언에 타입 매개변수가 쓰인 경우는 제네릭 클래스, 제네릭 인터페이스라고 합니다. 예를 들어서 List<E>와 같이 말입니다. 그리고 제네릭 클래스와 제네릭 인터페이스를 통틀어 제네릭 타입이라 합니다.

- 로 타입을 사용하면 어떻게 될까?

제네릭을 지원하기 전에는 컬렉션을 아래와 같이 사용했습니다.

private final Collection stamps = ...;
stamps.add(new Coin(...));
// unchecked call "경고"를 호출하지만 컴파일도 되고 실행도 된다.

위와 같은 코드는 컴파일 오류를 발생시키지 않으므로 실행중에 오류(Runtime Exception)가 발생할 수 있습니다. 예를 들어, add한 Coin 객체를 꺼내서 Stamp 변수에 할당하는 순간 ClassCastException이 발생할 수도 있습니다.

- 제네릭 지원 이후에는?

제네릭을 지원한 이후에는 아래와 같은 코드로 변경해서 사용합니다.

private final Collection<Stamp> stamps = ...;
stamps.add(new Coin()); // 컴파일 오류 발생.

컴파일 오류가 바로 발생합니다. 그렇다면 사용하지 않는 것을 권장하는데 왜 그대로 남겨두었을까요? 바로 제네릭이 등장하기 이전의 코드와의 호환성을 위해서 로 타입이 남겨졌습니다.

- 로 타입은 권장되지 않습니다.

List와 같은 로 타입은 권장하지 않지만 List<Object>는 괜찮습니다. 모든 타입을 허용한다는 의사를 컴파일러에게 명확하게 전달한 것이기 때문입니다. 그렇다면 ListList<Object>의 차이는 무엇일까요?

List는 제네릭 타입과 무관한 것이고, List<Object>는 모든 타입을 허용한다는 것입니다. 다시 말해서 매개변수로 List를 받는 메서드에 List<String>을 넘길 수 있지만, 제네릭의 하위 규칙 때문에 List<Object>를 받는 메서드에는 매개변수로 넘길 수 없습니다.