아이템 26 - 로 타입은 사용하지 말라.
JAVA ·로(raw) 타입이란?
- 제네릭 타입에서 타입 매개변수를 전혀 사용하지 않을 때를 말한다. (아무 타입이나 사용 가능)
- eg) List list = new ArrayList();
- 제네릭이 도래하기 전 코드와 호환되도록 하기 위한 궁여지책
매개변수화 타입을 사용해야 하는 이유
- 런타임이 아닌 컴파일 타임에 문제를 찾을 수 있다. (안정성)
- 제네릭을 활용하면 이 정보가 주석이 아닌 타입 선언 자체에 녹아든다. (표현력)
- “로 타입”을 사용하면 제네릭이 안겨주는 안정성과 표현력을 잃는다.
- 그렇다면 자바는 “로 타입”을 왜 지원하는가?
- List와 List
- 매개변수로 List를 받는 메서드에 List
을 넘길 수 있지만, List - 제네릭의 하위 타입 규칙 때문이다. 즉, List
은 로 타입인 List의 하위 타입이지만, List - 그 결과, List
- 매개변수로 List를 받는 메서드에 List
- Set과 Set<?>의 차이는?
- 간단히 말하자면, 와일드카드 타입은 안전하고, 로타입은 안전하지 않다.
- 로 타입 컬렉션에는 아무 원소나 넣을 수 있으니 타입 불변식을 훼손하기 쉽다
- 반면 Collection<?>에는 null 외에는 어떤 원소도 넣을 수 없다.
- 이 제약이 싫다면 제네릭 메서드나 한정적 와일드카드 타입을 사용하면 된다.
- 예외: class 리터럴과 instanceof 연산에는 로 타입을 써야 한다.
- 자바 명세는 class 리터럴에 매개변수화 타입을 사용하지 못하게 했다.
- 배열과 기본 타입은 허용한다.
- List.class, String[].class, int.class는 허용하고, List
.class와 List<?>.class는 허용하지 않는다.
- 런타임에는 제네릭 타입 정보가 지워지므로 instanceof 연산자는 비한정적 와일드 카드 타입 이외의 매개변수화 티입에는 적용할 수 없다.
- 그리고 로 타입이든 비한정적 와일드카드 타입이든 instanceof는 완전히 똑같이 동작한다.
- 비한정적 와일드카드 타입의 꺾쇠괄호와 물음표는 아무런 역할 없이 코드만 지저분하게 만드므로, 차라리 로 타입을 쓰는 편이 깔끔하다.
- 자바 명세는 class 리터럴에 매개변수화 타입을 사용하지 못하게 했다.