class Basket<T> {
private T item;
public Basket(T item) {
this.item = item;
}
public T getItem() {
return item;
}
public void setItem(T item) {
this.item = item;
}
}
class Basket<T> {
private T item1; // O
static T item2; // X
}
Integer, Double과 같은 래퍼 클래스를 활용한다.Basket<String> basket1 = new Basket<String>("Hello");
Basket<Integer> basket2 = new Basket<Integer>(10);
Basket<Double> basket3 = new Basket<Double>(3.14);
class Basket<T extends Flower> {
private T item;
...
}
위와 같이 코드를 작성하게 되면, 타입의 종류가 Flower의 하위 클래스로만 제한되게 된다.
또한 특정 클래스를 상속받은 클래스만 타입으로 지정할 수 있도록 제한하는 것뿐만 아니라, 특정 인터페이스를 구현한 클래스만 타입으로 지정할 수 있도록 제한할 수도 있다.
만약, 특정 클래스를 상속받으면서 동시에 특정 인터페이스를 구현한 클래스만 타입으로 지정할 수 있도록 제한하려면 아래와 같이 &를 사용하면 된다.(주의할 점은 클래스를 인터페이스보다 앞에 위치시켜야 한다.)
class Basket<T extends Flower & Plant> { // (1)
private T item;
...
}
class Basket {
public <T> void add(T element) {
}
}
class Basket<T> { // 1 : 여기에서 선언한 타입 매개변수 T와
public <T> void add(T element) { // 2 : 여기에서 선언한 타입 매개변수 T는 서로 다른 것이다.
}
}
static 메서드에서도 선언하여 사용할 수 있다.? 키워드로 사용할 수 있다.<? extends T>
<? super T>
<? extend T>는 와일드 카드에 상한 제한을 두는 것으로, T와 T를 상속받는 하위 클래스 타입만 타입 파라미터로 받을 수 있도록 지정한다.<? super T>는 와일드카드에 하한 제한을 두는 것으로, T와 T의 상위 클래스만 타입 파라미터로 받도록 한다.<?>는 <? extends Object>와 같다. 모든 클래스 타입은 Object 클래스를 상속받으므로, 모든 클래스 타입을 타입 파라미터로 받을 수 있음을 의미한다.public class Example {
public static void main(String[] args) {
PhoneFunction.call(new User<Phone>(new Phone()));
PhoneFunction.call(new User<IPhone>(new IPhone()));
PhoneFunction.call(new User<Galaxy>(new Galaxy()));
PhoneFunction.call(new User<IPhone12Pro>(new IPhone12Pro()));
PhoneFunction.call(new User<IPhoneXS>(new IPhoneXS()));
PhoneFunction.call(new User<S22>(new S22()));
PhoneFunction.call(new User<ZFlip3>(new ZFlip3()));
System.out.println("\n######################################\n");
// PhoneFunction.faceId(new User<Phone>(new Phone())); // X
PhoneFunction.faceId(new User<IPhone>(new IPhone()));
PhoneFunction.faceId(new User<IPhone12Pro>(new IPhone12Pro()));
PhoneFunction.faceId(new User<IPhoneXS>(new IPhoneXS()));
// PhoneFunction.faceId(new User<Galaxy>(new Galaxy())); // X
// PhoneFunction.faceId(new User<S22>(new S22())); // X
// PhoneFunction.faceId(new User<ZFlip3>(new ZFlip3())); // X
System.out.println("\n######################################\n");
// PhoneFunction.samsungPay(new User<Phone>(new Phone())); // X
// PhoneFunction.samsungPay(new User<IPhone>(new IPhone())); // X
// PhoneFunction.samsungPay(new User<IPhone12Pro>(new IPhone12Pro())); // X
// PhoneFunction.samsungPay(new User<IPhoneXS>(new IPhoneXS())); // X
PhoneFunction.samsungPay(new User<Galaxy>(new Galaxy()));
PhoneFunction.samsungPay(new User<S22>(new S22()));
PhoneFunction.samsungPay(new User<ZFlip3>(new ZFlip3()));
System.out.println("\n######################################\n");
PhoneFunction.recordVoice(new User<Phone>(new Phone()));
// PhoneFunction.recordVoice(new User<IPhone>(new IPhone())); // X
// PhoneFunction.recordVoice(new User<IPhone12Pro>(new IPhone12Pro())); // X
// PhoneFunction.recordVoice(new User<IPhoneXS>(new IPhoneXS())); // X
PhoneFunction.recordVoice(new User<Galaxy>(new Galaxy()));
// PhoneFunction.recordVoice(new User<S22>(new S22())); // X
// PhoneFunction.recordVoice(new User<ZFlip3>(new ZFlip3())); // X
}
}
