클라이언트에서 직접 형변환해야 하는 타입보단 제네릭 타입이 더 안전하고 쓰기 편하다.
- 클라이언트에서 불필요한 형변환 없음
- 훨씬 더 안정적으로 타입을 관리할 수 있다. (런타임 에러가 발생할 확률을 줄일 수 있다.)
사실 제네릭 타입 안에서 리스트를 사욯아는게 항상 가능하지도, 꼭 더 좋은 거도 아니다.
- 자바가 리스트를 기본 타입으로 제공하지 않으므로
ArrayList
같은 제네릭 타입도 결국은 기본 타입인 배열을 사용해 구현해야 한다. - 또한
HashMap
같은 제네릭 타입은 성능을 높일 목적으로 배열을 사용하기도 한다.
대다수의 제네릭 타입은 타입 매개변수에 아무런 제약을 두지 않는다.
Stack<Object>
,Stack<int[]>
,Stack<List<String>>
,Stack
등 어떤 참조 타입으로든 Stack을 만들 수 있다.- 단, 기본 타입은 사용할 수 없다.
- 이는 자바 제네릭 타입시스템의 근본적인 문제이나, 박싱된 기본 타입을 사용해 우회할 수 있다.
타입 매개변수에 제약을 두는 제네릭 타입도 있다.
- 예컨대
java.util.concurrent.DelayQueue
는 아래처럼 선언되어 있다.
1
class DelayQueue<E extends Delayed> implements BlockingQueue<E>
- Delayed 클래스의 하위 타입만 받는 다는 뜻이다.
- 이렇게 하여 DelayQueue 자신과 DelayQueue를 사용하는 클라이언트에서 DelayQueue의 원소에서 (형변환 없이) 곧바로 Delayed 클래스의 메서드를 호출할 수 있다.(ClassCastException 걱정은 할 필요가 없다.)
- 이러한 타입 매개변수 E를 한정적 타입 매개변수라 한다.
핵심 정리: 클라이언트에서 직접 형변환해야 하는 타입보단 제네릭 타입이 더 안전하고 쓰기 편하다. 그러니 새로운 타입을 설계할 때는 형변환 없이도 사용할 수 있도록 하라. 그렇게 하려면 제네릭 타입으로 만ㄷ르어야 할 경우가 많다. 기존 타입 중 제네릭이었어야 하는게 있다면 제네릭 타입으로 변경하자. 기존 클라이언트에는 아무 영향을 주지 않으면서, 새로운 사용자를 훨씬 편하게 해주는 길이다.