제네릭(Generic) - 3
제네릭(Generic) 와일드 카드
제네릭의 특정 범위 내로 좁혀서 제한하고 싶다면 어떻게 해야할까?
와일드 카드의 타입 범위를 제한하는 키워드는 extends 와 더불어 super가 있다.
이 extends 와 super 키워드는 클래스 상속 관계에서의 타입을 하위 타입으로만 제한할지, 상위 타입으로만 제한할지에 따라 쓰임새가 다르게 된다.
- 제네릭(Generic) 와일드 카드 종류
| 와일드카드 | 타입 | 설명 |
|---|---|---|
| < ? > | 비한정적 와일드 카드 | 제한 없음(모든 타입 가능) |
| < ? extends E> | 상한 경계 와일드 카드 | 상위 클래스 제한(E와 그 자순들만 가능) |
| < ? super E> | 하한 경계 와일드 카드 | 하위 클래스 제한(E와 그 조상들만 가능) |
< K extends E >, < ? extends E >
이것은 E 타입을 포함한 자식(자손) 타입만 가능하다는 의미다.
예시를 들자면 제네릭 클래스에서 수를 표현하는 클래스만 받고 싶은 경우가 있다. 대표적인 Integer, Long, Byte, Double, Float, Short 같은 래퍼 클래스들은 Number 클래스를 상속 받는다.
그래서 Integer, Long, Byte, Double, Float, Short 같은 수를 표현하는 래퍼 클래스만으로 제한하고 싶은 경우 다음과 같이 쓸 수 있다.
public class ClassName <E extends Number> { ... }
이렇게 특정 타입 및 그 하위 타입만 제한 하고 싶을 경우 쓰면 된다.
그래서 Integer는 Number 클래스를 상속받는 클래스라 가능하지만, String은 Number클래스와는 완전 별개의 클래스이기 때문에 에러를 발생시킨다.
1
2
3
4
5
6
7
8
9
10
11
12
public class ClassName <E extends Number> {
...
}
public class Main {
public static void main(String[] args) {
ClassName<Double> a = new ClassName<Double>(); // SUCCESS!
ClassName<String> b = new ClassName<String>(); // ERROR!
}
}
< K super T >, <? super T>
이 것은 T 타입의 부모(조상) 타입만 가능하다는 의미다.
대표적으로는 해당 객체가 업캐스팅(Up Casting)이 될 필요가 있을 때 사용한다.
예시로 ‘동물’이라는 클래스가 있으며, 이 클래스를 각각 상속받는 ‘강아지’클래스와 ‘고양이’클래스가 있다고 하자.
이 때 각각의 강아지와 고양이는 종류가 다르지만, 둘 다 ‘동물’로 보고 자료를 조작해야 할 수도 있다.
여기서 ‘강아지’를 ‘동물’로 캐스팅 해야 하는데, 동물이 상위 타입이므로 업캐스팅을 해야한다.
그래서 쓸 수 있는 것이 바로 super라는 것이다.