Java/객체지향

[객체지향][제네릭스] - 와일드카드, 제네릭 메서드

얄루몬 2022. 2. 20. 23:01

 

📖본 포스팅은 '자바의 정석 - 남궁성 저자' 님의 책과 유튜브 강의를 보고 작성되었습니다.
https://youtu.be/LL3PWmGFuQA?list=PLW2UjW795-f6xWA2_MUhEVgPauhGl3xIp


[와일드 카드<?>]

  • 하나의 참조 변수로 대입된 타입이 다른 객체를 참조 가능한 것
  • <? extends T> 
    • 와일드 카드 상한 제한 T와 그 자손들만 가능
    • 제일 많이 사용함.
  • <? super T>
    • 와일드 카드 하한 제한 T와 그 조상들만 가능
  • <?>
    • 제한 없음 모든 타입이 가능하고 <? extends Object>와 동일
  • 다형성을 떠올리면 와일드 카드 개념을 이해하기 쉽다.
  • 메서드의 매개변수에 와일드 카드 사용

 

 

[와일드 카드 실습]

package javajungsuk;

import java.util.ArrayList;

class Fruit{public String toString() {return "Fruit";}}
class Apple extends Fruit{public String toString() {return "Apple";}}
class Grape extends Fruit{public String toString() {return "Grape";}}


class Juice {
	String name;
	Juice(String name){this.name = name+"Juice";}
	public String toString() {return name;}
}

class Juicer{
	static Juice makeJuice(FruitBox<? extends Fruit> box) {
		String tmp ="";
		for(Fruit f : box.getList())
			tmp += f+" ";
		return new Juice(tmp);
	}
}



public class Java12_4 {
	public static void main(String[] args) {
		//원래 참조변수에 대입된 제네릭 타입과 생성자에 대입된 제네릭 타입이 일치해야 한다!
		FruitBox<Fruit> fruitBox = new FruitBox<Fruit>();
		FruitBox<Apple> appleBox = new FruitBox<Apple>();
		
		
		fruitBox.add(new Apple());
		fruitBox.add(new Grape());
		appleBox.add(new Apple());
		appleBox.add(new Apple());
		
		System.out.println(Juicer.makeJuice(fruitBox));
		System.out.println(Juicer.makeJuice(appleBox));
	}
}


class FruitBox<T extends Fruit> extends Box<T>{}

class Box<T>{
	ArrayList<T> list = new ArrayList<T>();
	void add(T item) {list.add(item);}
	T get(int i) {return list.get(i);}
	ArrayList<T> getList() {return list;}
	int size() {return list.size();}
	public String toString() {
		return list.toString();
	}
		
	

}
		//FruitBox<Apple> appleBox = new FruitBox<Apple>();
		//Fruit를 쓰고 싶을때 -> 와일드 카드 사용!!
		FruitBox<? extends Fruit> appleBox = new FruitBox<Apple>();
		appleBox = new FruitBox<Fruit>();
		appleBox = new FruitBox<Apple>();
		appleBox = new FruitBox<Grape>();
  • 와일드 카드를 사용해서 참조 변수에 대입된 제네릭 타입과 생성자에 대입된 제네릭 타입이 달라도 사용할 수 있게 만드는 방법을 배웠다.

 

 

[제네릭 메서드]

  • 제네릭 타입이 선언된 메서드를 말한다.(타입 변수는 메서드 내에서만 유효하다.)
class FruitBox<T> { //<--제네릭 클래스
	...
	static <T> void sort(List<T list, Comprator <? super T> c>) {
		// 제네릭 메서드고 지네릭 클래스와 타입변수가 다르다!!!!
		//또한 제네릭 메서드가 제네릭 클래스보다 우선한다!
		...
	}
}

 

  • 메서드 호출 마다 타입을 대입해야 한다.(대부분 생략 가능하다.)

 

  • 메서드를 호출할 때 타입을 생략하지 않을 때는 클래스 이름은 생략 불가하다.
    • 에러가 나면 생략하지 않고 다 적어주면 된다. 
    • 에러가 나는 경우가 매우 드물다!