- List
- 이는 리스코프 치환 원칙에 어긋난다.
- 리스코프 치환 원칙 : 부모 객체와 이를 상속한 자식 객체가 있을 때 부모 객체를 호출하는 동작에서 자식 객체가 부모 객체를 완전히 대체할 수 있다.
// 와일드카드 타입을 사용하지 않은 pushAll 메서드 - 결함
public void pushAll(Iterable<E> src) {
for (E e : src)
push(e);
}
// 생산자(producer) 매개변수에 와일드카드 타입 적용
public void pushAll(Iterable<? extends E> src) {
for (E e : src)
push(e);
}
// 와일드카드 타입을 사용하지 않은 popAll 메서드 - 결함
public void popAll(Collection<E> dst) {
while (!isEmpty())
dst.add(pop());
}
// E 소비자(consumer) 매개변수에 와일드카드 타입 적용
public void popAll(Collection<? super E> dst) {
while (!isEmpty())
dst.add(pop());
}
pollALL 의 입력 매개변수 타입이 ‘E의 Collection’이 아니라 “E의 상위 타입의 Collection”이어야 한다.
- 겟풋 원칙 : Get and Put Principle
public static <E> Set<E> union(Set<? extends E> s1, Set<? extends E> s2)
- void add(int value){…}
- add(10);
- class Set
{...}
- Set
= ...
public static <E extends Comparable<E>> E max(List<E> list)
public static <E extends Comparable<? super E>> E max(List<? extends E> list)
List<ScheduledFuture<?>> scheduledFutures = ... ;
public interface Comparable<E>
public interface Delayed extends Comparable<Delayed>
public interface ScheduledFuture<V> extends Delayed, Future<V>
List<E>
>List<?>
<E extends Number>
>List<? extends Number>
public static <E> void swap(List<E> list, int i, int j);
public static void swap(List<?> list, int i, int j); // 더 좋은 방법
public static void swap(List<?> list, int i, int j) {
list.set(i, list.set(j, list.get(i)));
}
public static void swap(List<?> list, int i, int j) {
swapHelper(list, i, j);
}
// 와일드카드 타입을 실제 타입으로 바꿔주는 private 도우미 메서드
private static <E> void swapHelper(List<E> list, int i, int j) {
list.set(i, list.set(j, list.get(i)));
}
- producer-extends, consumer-super
Reference: