제한된 타입 파라미터(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); //과일(사과), 과일(사과) => 쥬스 완성!!! 출력