public class GenericTest<T> {
private T value;
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
// 제네릭 클래스의 T(타입)에 해당하는 부분이 모두 Integer로 변환된다.
GenericTest<Integer> gt = new GenericTest<Integer>();
import com.ohgiraffers.section02.extend.vo.*;
public class Application1 {
public static void main(String[] args) {
/* 수업목표. extends 키워드를 사용하여 특정 타입만 제네릭 타입으로 사용하도록 제한할 수 있다. */
/* 설명. Rabbit이거나 Rabbit의 자식 타입이 아닌 타입으로 제네릭 타입을 지정하면 컴파일 에러가 발생한다. */
// RabbitFarm<Animal> farm1 = new RabbitFarm<Animal>();
// RabbitFarm<Snake> farm2 = new RabbitFarm<Snake>();
// RabbitFarm<Mammal> farm3 = new RabbitFarm<Mammal>();
/* 설명. Rabbit 또는 Rabbit의 자식 타입으로는 인스턴스 생성이 가능하다. */
RabbitFarm<Rabbit> farm4 = new RabbitFarm<>();
RabbitFarm<Bunny> farm5 = new RabbitFarm<>();
RabbitFarm<DrunkenRabbit> farm6 = new RabbitFarm<>();
farm4.setAnimal(new Rabbit());
farm4.getAnimal().cry();
farm4.setAnimal(new Bunny());
farm4.getAnimal().cry(); // 동적 바인딩에 의해 반환형인 Animal의 cry()가 아닌 Bunny의 cry()가 실행됨
farm5.setAnimal(new Bunny());
farm5.getAnimal().cry();
farm6.setAnimal(new DrunkenRabbit());
farm6.getAnimal().cry();
}
}public class Bunny extends Rabbit{
@Override
public void cry() {
System.out.println("바니바니 바니바니 당근당근!");
}
}public class DrunkenRabbit extends Rabbit{
@Override
public void cry() {
System.out.println("봐니봐니 봐니뽜니 당근! 당근! @#%#?!#");
}
}public class Rabbit extends Mammal {
public void cry() {
System.out.println("토끼가 울음소리를 냅니다. 끾끾!");
}
}
제네릭 클래스의 인스턴스를 유연하게 활용하기 위한 문법. 메소드의 매개변수로 받을 시 타입을 원하는 만큼으로 제한하는 것으로 불특정한 제네릭 클래스 타입을 조금 더 활용할 수 있다.
- < ? >: 모든 타입을 허용하는 와일드 카드
- < ? extends T>: T 타입 또는 T의 하위 타입을 허용하는 와일드 카드
- < ? super T>: T 타입 또는 T의 상위 타입을 허용하는 와일드 카드
import com.ohgiraffers.section02.extend.vo.*;
public class Application2 {
public static void main(String[] args) {
/* 수업목표. 와일드카드에 대해 이해할 수 있다. */
WildCardFarm wildCardFarm = new WildCardFarm();
wildCardFarm.anyType(new RabbitFarm<Rabbit>());
wildCardFarm.anyType(new RabbitFarm<Bunny>());
wildCardFarm.anyType(new RabbitFarm<DrunkenRabbit>());
wildCardFarm.extendsType(new RabbitFarm<Bunny>());
// wildCardFarm.extendsType(new RabbitFarm<Rabbit>());
// wildCardFarm.extendsType(new RabbitFarm<DrunkenRabbit>());
wildCardFarm.superType(new RabbitFarm<Rabbit>());
wildCardFarm.superType(new RabbitFarm<Bunny>());
// wildCardFarm.superType(new RabbitFarm<DrunkenRabbit>());
}
}import com.ohgiraffers.section02.extend.vo.Bunny;
import com.ohgiraffers.section02.extend.vo.RabbitFarm;
/* 필기.
* 와일드카드(wildcard)
* 제네릭 클래스 타입의 객체를 메소드의 매개변수로 받을 때 타입 변수를 제한할 수 있다.
* <?>: 제한 없음
* <? extends Type): 와일드카드의 상한 제한(Type과 Type의 후손을 이용해 생성된 제네릭의 인스턴스만 가능)
* <? super Type): 와일드카드의 하한 제한(Type과 Type의 부모를 이용해 생성된 제네릭 인스턴스만 가능)
* */
public class WildCardFarm {
/* 설명. 어떤 타입의 RabbitFarm(제네릭 타입)이 와도 상관 없다. */
public void anyType(RabbitFarm<?> farm) { // RabbitFarm<T extends Rabbit> 아무나
farm.getAnimal().cry();
}
/* 설명. RabbitFarm 중에서도 Bunny 또는 Bunny 하위 타입이 있는 RabbitFarm만 가능(Bunny 제네릭의 농장만 가능) */
public void extendsType(RabbitFarm<? extends Bunny> farm) {
farm.getAnimal().cry();
}
/* 설명. RabbitFarm 중에서도 Bunny 상위 타입이 있는 RabbitFarm만 가능(Bunny이거나 Rabbit 제네릭의 농장만 가능) */
public void superType(RabbitFarm<? super Bunny> farm) {
farm.getAnimal().cry();
}
}