[Java] 7. 제네릭-와일드카드(Wildcard) 타입


제네릭에 와이드카드를 코드에 따른 주석으로 설명한 포스팅이다.



1. 제네릭 와일드카드(wildcard)

자바의 제네릭에서 알 수 없는 타입을 제한하고 싶을 때 와일드카드 문자인 ?를 사용한다.


<? extends T> : 와일드 카드의 상한 제한. T와 그 자손들만 가능
<? super T> : 와일드 카드의 하한 제한. T와 그 조상들만 가능
<?> : 제한 없음. 모든 타입의 가능. <? extends Object>와 동일 åå



2. 와일드카드 예제

포스팅 설명 대신 예제 코드와 주석으로 대신한다.


Fruit.java

//음식
class Food {
}

//과일
class Fruit<T> extends Food {
}

//사과
class Apple extends Fruit {
}

//바나나
class Banana extends Fruit {
}

class FruitBox<T extends Fruit> {

    private T fruitName;

    ArrayList<T> list = new ArrayList<T>();

    void add(T fruit) {
        this.add(fruit);
    }

    T get(int i) {
        return list.get(i);
    }

    int size() {
        return list.size();
    }
}


class Cart<T> {
}



ExGenericTypeExtends.java

public class ExGenericTypeExtends {

    public static void main(String... args) {

        //FruitBox 는 과일 클래스를 상속 받는 과일만 생성자로 만들 수 있다.
        //T는 자손 타입을 미리 정의해놓고 사용하는 방법

        //EX CASE 1
        FruitBox<Fruit> fruitBox = new FruitBox<Fruit>();
        fruitBox = new FruitBox<Fruit>();
        //과일로 과일박스를 만들면
        //부모인 fruit 으로는 자식인 과일 종류(Apple, Banana)들을 담을 수가 있다.
        fruitBox.add(new Apple());
        fruitBox.add(new Banana());


        //EX CASE 2
        //사과로 사과박스를 만들면 사과(Apple)만 담을 수 있다.
        FruitBox<Apple> appleBox = new FruitBox<Apple>();
        appleBox.add(new Apple());
        //appleBox.add(new Banana());//에러 발생, 사과박스에 바나나를 담으려고 해서 에러


        //EX CASE 3 : 와일드카드
        //3-1. <? extends T> : 와일드 카드의 상한 제한. T와 자손들만 가능
        //와일드 카드로 <? extends Fruit> 다형성으로 과일 자식(Apple, Banana)들 객체 모두 대입이 가능하다.
        FruitBox<? extends Fruit> fruitWildBox = new FruitBox<Fruit>();
        fruitWildBox = new FruitBox<Fruit>();
        fruitWildBox = new FruitBox<Apple>();
        fruitWildBox = new FruitBox<Banana>();

        //3-2. <? super T> : 와일드 카드의 하한 제한. T와 조상들만 가능
        Cart<? super Fruit> foodSuperCart = new Cart<Fruit>();
        foodSuperCart = new Cart<Food>();
        foodSuperCart = new Cart<Fruit>();
        //foodSuperCart = new Cart<Apple>();//에러 발생, 자손은 불가


        //EX CASE 4 : 메서드의 매개변수에 와이드 카드 예제
        //4-1. 와일드 카드 없는 경우 : FruitBox<Fruit> fruit
        //지정 된 타입만 대입이 가능
        FruitCart.addOnlyFruitCart(new FruitBox<Fruit>());
        //FruitCart.addOnlyFruitCart(new FruitBox<Apple>());//에러 발생

        //4-2. <? extends T> : FruitBox<? extends Fruit> fruit
        //와일드 카드의 상한 제한. T와 자손들만 가능
        FruitCart.addWildCart1(new FruitBox<Fruit>());
        FruitCart.addWildCart1(new FruitBox<Apple>());

        FruitCart.addWildCart2(new FruitBox<Fruit>());
        FruitCart.addWildCart2(new FruitBox<Banana>());

        //4-3. <? super T> : Cart<? super Fruit> fruit
        //와일드 카드의 하한 제한. T와 조상들만 가능
        FruitCart.addSuperCart(new Cart<Food>());
        FruitCart.addSuperCart(new Cart<Fruit>());
        //FruitCart.addSuperCart(new Cart<Apple>());//에러, 자손 불가
    }


    static class FruitCart {

        //과일박스의 Fruit 만 들어 올 수 있음
        //- new FruitBox<Fruit>()
        static void addOnlyFruitCart(FruitBox<Fruit> fruit) {
        }

        //와이드카드로 과일박스 자기와 자손들도 가능 Fruit, Apple, Banana
        //- new FruitBox<Fruit>()
        //- new FruitBox<Apple>()
        static <T extends Fruit> void addWildCart1(FruitBox<T> fruit) {
        }

        //addWildCart1 와 addWildCart2 메서드는 동일함
        static void addWildCart2(FruitBox<? extends Fruit> fruit) {
        }

        //와일드카드 super 로 자기와 조상들만 가능 Fruit, Food
        static void addSuperCart(Cart<? super Fruit> fruit) {
        }
    }
}


헤당 포스팅도 끝