매개변수화 타입은 상위 타입 하위 타입 개념이 존재하지 않는다.
예를 들어, List<Object> 를 List<String> 의 상위 타입이라 할 수 없다. (List<Object> 는 어떤 객체든 넣을 수 있지만 List<String> 은 String 만 넣을 수 있다. 즉, 리스코프 치환 원칙에 어긋난다.)
문제점
Object 처럼 String을 사용할 수는 있는데 이것도 안되는건 논리적으로 이해가 잘 되지 않는다.
해결 방안
한정적 와일드카드
를 사용하여 API의 유연성을 높일 수 있다.
<? extends E> - E 의 하위 타입을 허용
<? super E> - E의 상위 타입을 허용
그렇다면 언제 해당 타입의 상위타입을, 하위 타입을 적용해야 할까?
PECS (produces-extends, consumer-super) 를 기억하자.
Stack<E> 를 예로 들어보자.
pushAll 은 Stack 에 원소를 생산해주는 것이므로 생산자, <? extends E> 를 사용할 때 적합하다.
popAll 은 Stack의 원소를 소비하는 것이므로 소비자, <? super E> 를 사용하면 적합하다.
메서드 매개변수가 한 번만 나오면 와일드 카드로 대체하자. - 클라이언트의 사용성을 높이기 위함, API를 만드는 사람은 오히려 복잡한 코드를 작성하게 된다.
주의점
반환 타입은 와일드 카드를 사용하지 말자 - 클라이언트에서도 와일드 카드를 사용해야 하기 때문