1. 지네릭 타입과 다형성
앞서 참조 변수의 타입과 인스턴스의 타입은 다형성(조상이 자손 참조)이 가능하지만 지네릭 타입은 서로 일치해야 한다.
(1) ArrayList<Tv> list = new ArrayList<Tv>(); // O
(2) ArrayList<Product> list = new ArrayList<Tv>(); // X
(3) List<Tv> list = new ArrayList<Tv>(); // O
(4) List<Product> list = new ArrayList<Tv>(); // X
원시 타입 | 지네릭 타입 | |
다형성 가능 여부 | O | X |
ArrayList<Product> product = new ArrayList<Product>(); 를 사용해 product의 ArrayList에 Product 타입의 자손 객체를 담을 수 있다. 이때 형변환을 해야함을 잊지 말자.
2. 지네릭 타입의 제한
대입되는 지네릭 타입을 제한해줄 때는 다음과 같이 한다.
class FruitBox<T extends Fruit & Eatable> {
....
}
이때 타입 매개변수 T에는 Fruit과 그 자손 객체만 대입이 가능하다. 인터페이스 구현 시에도 extends를 사용하며 extends 뒤에 두 개 이상의 타입이 올 때는 &로 연결한다.
[예 2-1]
참고
3. 와일드 카드
지네릭스의 와일드 카드는 1에서 불가능했던 지네릭 타입 간에 다형성을 가능하게 해준다.
?에 올 수 있는 타입 | |
(1) <? extends T> | T와 그 자손 객체들 (? <= T) |
(2) <? super T> | T와 그 조상 객체들 (? >= T) |
(3) <?> (<? extends Object>) | 모든 타입 |

[예 3-1]
static Juice makeJuice(FruitBox<? extends Fruit> box) {
String tmp = "";
....
return new Juice(tmp);
}
Juice.makeJuice(new FruitBox<Fruit>()); // O
Juice.makeJuice(new FruitBox<Apple>()); // O
[참고] 와일드 카드와 지네릭 메서드
와일드 카드 | 지네릭 메서드 | |
예 | static Juice makeJuice(FruitBox<? extends Fruit> box) { String tmp = ""; .... return new Juice(tmp); } |
static <T extends Fruit> makeJuice(FruitBox<T> box) { String tmp = ""; .... return new Juice(tmp); } |
용도 | 하나의 참조 변수로 여러 지네릭 타입을 다루기 위함 | 메서드를 호출할 때마다 서로 다른 타입을 대입할 수 있게 함 |
둘의 용도를 잘 구별하고 보통 와일드 카드가 안될 때 지네릭 메서드를 쓰고는 한다. 둘의 차이에 대해 너무 신경 쓰지 말고 일단 사용하는데 집중하자.
[참고] 타입 (매개)변수 (T) vs. 지네릭 타입 (<T>)
static 멤버에는 T를 못 쓰지 <T>는 사용할 수 있다. 둘을 혼동하지 않도록 하자.
4. 지네릭 타입의 형변환
1) 지네릭 타입 ↔ 원시 타입
Box box = null;
Box<Object> objBox = null;
box = (Box) objBox; // 지네릭 타입 → 원시 타입 (O)
objBox = (Box<Object>) box; // 원시 타입 → 지네릭 타입 (O)
하지만 둘 다 경고가 발생한다.
2) (서로 다른 지네릭 타입 간) 지네릭 타입 ↔ 지네릭 타입
1에서도 알 수 있듯이 불가하다.
3) 지네릭 타입 → 와일드 카드를 포함한 지네릭 타입
Box<? extends Object> wBox = new Box<String>();
Box<String> sBox = (Box< String>) wBox; // 와일드 카드를 포함한 지네릭 타입 → 지네릭 타입 (O)
[예 3-1]을 참고하면 다음과 같다.
FruitBox<? extends Fruit> box = (FruitBox<? extends Fruit>) new FruitBox<Fruit>();
FruitBox<? extends Fruit> box = (FruitBox<? extends Fruit>) new FruitBox<Apple>();
모두 해당 형변환이 생략돼 있었던 것이다.
5. 지네릭 타입의 제거
컴파일러는 컴파일 전 지네릭 타입을 제거하고 필요하면 형변환을 추가해준다.
'자바 (Java) > 요약' 카테고리의 다른 글
Chpt 12. 지네릭스, 열거형, 애너테이션 - 주제 4. 애너테이션 (0) | 2023.11.10 |
---|---|
Chpt 12. 지네릭스, 열거형, 애너테이션 - 주제 3. 열거형 (0) | 2023.11.10 |
Chpt 12. 지네릭스, 열거형, 애너테이션 - 주제 1. 지네릭스 (0) | 2023.11.10 |
Chpt 11. 컬렉션 프레임워크 - 주제 7. Comparator vs. Comparable (0) | 2023.11.08 |
Chpt 11. 컬렉션 프레임워크 - 주제 5. Map 인터페이스와 구현 클래스들 (0) | 2023.11.08 |