Lonely Snowman
 

[JAVA] 제한된 타입 파라미터와 와일드카드

제한된 타입 파라미터(Bounded Type Parameter)
Generic을 이용한 타입에 대해 구체적으로 타입 제한할 경우에 사용

 

<T extends 제한타입>	//제한타입과 그 자손타입들만 가능

 

 

와일드카드
? 기호를 쓴다.
제너릭이 사용된 객체를 참조할 때 참조할 객체의 타입을 제한하기 위해 사용한다.
아직 결정되지 않은 타입을 위한 표기법

 

<? extends T>	//와일드카드의 상한 제한. T와 그 자손들만 가능
<? super T>	//와일드카드의 하한 제한. T와 그 조상들만 가능(Object 제외)
<?>		//모든 허용 가능한 타입이 가능

 

 

 

 

예시 1

Util2 클래스 안에 Generic 메서드를 만들었다.

<T extends Number>를 써서 넘버 타입만 들어올 수 있도록 해주었다.

들어온 인자들은 Double타입으로 변환 후 값을 비교해서 1, 0, -1 중 하나의 값으로 리턴한다.

class Util2 {
	public static <T extends Number> int compare(T t1, T t2) {
		
        double v1 = t1.doubleValue();
        double v2 = t2.doubleValue();
        
        return Double.compare(v1, v2);
	}
}

 

정수로만 입력해도 되고, 실수 정수 섞어도 잘 출력된다.

하지만 문자열로 입력하면 컴파일에러가 난다.

public class T04GenericMethodTest {
	public static void main(String[] args) {
    	
        int result1 = Util2.compare(10, 20);
        System.out.println(result1);				//-1 출력
        
        int result2 = Util2.compare(3.14, 3);
        System.out.println(result2);				//1 출력
        
        System.out.println(Util2.compare("C", "JAVA"));		//에러
	}
}

 

 

 

 

예시 2

과일 클래스들을 만들고 과일박스 클래스도 만들었다.

FruitBox 클래스는 Fruit 타입만 들어올 수 있게 했다.

add 메서드도 Fruit 타입만 들어올 수 있다.

class Fruit {
	private String name;

	public Fruit(String name) {
		super();
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "과일(" + name + ")";
	}
}


class Apple extends Fruit {
	public Apple() {
		super("사과");
	}
}


class Grape extends Fruit {
	public Grape() {
		super("포도");
	}
}


class FruitBox<T extends Fruit> {
	
	private List<T> fruitList;
	
	public FruitBox() {
		fruitList = new ArrayList<>();
	}

	public List<T> getFruitList() {
		return fruitList;
	}
	
	public void add(T fruit) {
		fruitList.add(fruit);
	}
}

 

Fruit 타입이 들어갈 fruitBox와 Apple 타입이 들어갈 appleBox를 만들고

객체를 만들어서 add 메서드로 리스트에 추가해 봤다

add 메서드는 박스에 맞는 타입만 들어갈 수 있어서 appleBox에 Grape는 안 들어간다

public class T05WildCardTest {
	public static void main(String[] args) {
    	FruitBox<Fruit> fruitBox = new FruitBox<>();
        FruitBox<Apple> appleBox = new FruitBox<>();
		
		fruitBox.add(new Apple());
		fruitBox.add(new Grape());
		
		appleBox.add(new Apple());
//		appleBox.add(new Grape());			//에러
		appleBox.add(new Apple());
	}
}

 

박스에 add 한 과일들을 담아서 쥬스완성! 출력하는 makeJuice 메서드를 Juicer 클래스 안에 만들었다.

이번에는 와일드카드를 사용했다.

class Juicer {
	static void makeJuice(FruitBox<?> box) {
		
		String fruitListStr = "";
		
		int cnt = 0;
		for (Object f : box.getFruitList()) {
			if(cnt==0) {
				fruitListStr += f;
			}else {
				fruitListStr += ", " + f;				
			}cnt++;
		}
		System.out.println(fruitListStr + " => 쥬스 완성!!!");
	}
}

 

메인메서드에 makeJuice 메서드 사용하면 잘 출력된다.

Juicer.makeJuice(fruitBox);		//과일(사과), 과일(포도) => 쥬스 완성!!! 출력
Juicer.makeJuice(appleBox);		//과일(사과), 과일(사과) => 쥬스 완성!!! 출력