ArrayList<? extends Product> list = new ArrayList<Tv>(); // OK
ArrayList<? extends Product> list = new ArrayList<Audio>(); // OK
ArrayList<Product> list = new ArrayList<Tv>(); // 에러. 지네릭 타입 불일치
지네릭 클래스를 생성할 때, 참조변수에 지정된 지네릭 타입과 생성자에 지정된 지네릭 타입은 일치해야 한다. 만일 일치하지 않으면 다음과 같이 컴파일 에러가 발생한다. Product와 Tv가 서로 상속관계라도 마찬가지이다.
<? extends T> 와일드 카드의 상한 제한. T와 그 자손들만 가능
<? super T> 와일드 카드의 하한 제한. T와 그 조상들만 가능
<?> 제한없음. 모든 타입이 가능. <? extends Object>와 동일
<? extends Product>
의미 : Product와 그 자손들
이 예제에서는 Product, Tv, Audio클래스가 이에 해당한다.
<? super Product>
의미 : Product와 그 조상들
이 예제에서는 Product, Object클래스가 이에 해당한다.
메서드의 매개변수에 와일드 카드를 사용
static Juice makeJuice(FruitBox<? extends Fruit> box) {
String tmp = "";
for(Fruit f : box.getList()) tmp += f + " ";
return new Juice(tmp);
}
System.out.println(Juicer.makeJuice(new FruitBox<Fruit>()))); // OK
System.out.println(Juicer.makeJuice(new FruitBox<Apple>()))); // OK
이렇게 메서드 매개변수로 와일드 카드를 사용하면 FruitBox<Fruit>와 FruitBox<Apple> 둘 다 인자로 사용할 수 있다. 와일드 카드를 사용하지 않는다면 FruitBox<Fruit>만 들어올 수 있을 것이다.
static Juice makeJuice(FruitBox<? extends Fruit> box) { // ...
의미 : Fruit와 그 자손들
이 예제에서는 Fruit, Apple클래스가 이에 해당한다.
이처럼 메서드의 매개변수에 와일드 카드를 사용하면, 다형성 효과를 얻을 수 있다. 서로 대입된 지네릭 타입이 다른 객체들을 하나의 매개변수로 받을 수 있게 되는 것이다.