고급 JAVA

JAVA - Generic 와일드 카드

햄찌개 2020. 9. 17. 20:43

 * 와일드 카드 예제
 *<? extends T> => 와일드 카드의 상한 제한. T와 그 자손들만 가능 
 *<? super T> => 와일드 카드의 하한 제한. T와 그 조상들만 가능 
 * <?>  => 모든타입이 가능 <? extends Object>와 동일

public class T05_WildCardTest {
	public static void main(String[] args) {
		FruitBox<Fruit> fruitBox = new FruitBox(); //과일상자
		FruitBox<Apple> appleBox = new FruitBox();	//t사과상자
		
		fruitBox.add(new Apple());
		fruitBox.add(new Grape());
		
		appleBox.add(new Apple());
		appleBox.add(new Apple());

		Juicer.makeJuice(fruitBox);	//과일 상자인 경우에는 아무런 문제 없음 .
		Juicer.<Apple>makeJuice(appleBox);	
		
		
		
	}

}
class Juicer{
	//static void makeJuice(FruitBox<Fruit> box){ //fruitBox만 가능 
	//static <T> void makeJuice(FruitBox<T> box) { //과일 상자 모두가능 
	//static<T extends Fruit> void makeJuice(FruitBox<T> box) {	//제한된~~ 이용 
	static void makeJuice(FruitBox<? extends Fruit> box) { //와일드 카드 이용  //어떤 타입인지는 모르지만 Fruit를 extends 한 타입 
	String fruitstr = "";//과일 목록
		
		int cnt = 0;
		
		for (Fruit f : box.getFruitList()) {
			if(cnt ==0) {
				fruitstr+=f;
			}else {
				fruitstr+= ","+f;
			}
			cnt++;
		}
		System.out.println(fruitstr +" => 쥬스 완성 !!"); 
		
	}
}







/**
 * 과일
 *
 */
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 = " + name + "]" ;
	}
	
}
//사과
class Apple extends Fruit{
	public Apple() {
		super("사과");
	}
}
//포도
class Grape extends Fruit{
	public Grape() {
		super("포도");
	}
}

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

	public List<T> getFruitList() {
		return fruitList;
	}

	public void setFruitList(List<T> fruitList) {
		this.fruitList = fruitList;
	}
	
	public void add(T fruit) {
		fruitList.add(fruit);
	}
	
	
	
	
	
}

public class T06_WildCardTest {

	public static void main(String[] args) {
		
		//FruitBox2<? extends Fruit> fruitBox1 = new FruitBpx2<Fruit>);
		FruitBox2<?> fruitBox1 = new FruitBox2();
		FruitBox2<?> fruitBox2 = new FruitBox2();//위와 동일 
		
		//FruitBox2<?>는  FruitBox2<? extends Fruit>를 의미함 
	//	FruitBox2<?> fruitBox3 = new FruitBox2<Object>();
		
		// 두 타입 (Object, Fruit)이 일치하지 않음 
	//	FruitBox2<Object> fruitBox4 = new FruitBox2<Fruit>(); 
		
		
		FruitBox2<?> fruitBox5 = new FruitBox2<Fruit>(); 
		FruitBox2<? extends Fruit> fruitBox6 = new FruitBox2<Apple>(); 
		
		//new 연산자는 타입이 명확해야 객체생성을 할 수 있다.(와일드 카드 사용 불가)
	//	FruitBox2<? extends Object> fruitBox7 = new FruitBox2<? extends Object>(); 
		
	}
}

/**
 * 과일상자2
 *
 * @param <T>
 */
class FruitBox2<T extends Fruit>{
	List<T> itemList = new ArrayList<>();
	
	
	public void addItem(T item) {
		this.itemList.add(item);
	}


	public List<T> getItemList() {
		return itemList;
	}


	public void setItemList(List<T> itemList) {
		this.itemList = itemList;
	}


}