이 글은 유튜브 '자바의 정석 - 기초편'을 보고 정리한 글입니다.
📂content
1. 제네릭 타입의 형변환
- 제네릭 타입과 원시 타입 간의 형변환은 바람직하지 않다. (경고 발생)
Box<Object> objBox = null;
Box box = (Box)objBox; //OK. 제네릭 타입(Box<Object>) -> 원시 타입(Box). 경고 발생
objBox = (Box<Object>)box; //OK. 원시 타입(Box) -> 제네릭 타입(Box<Object>). 경고 발생
Ex12_3을 이용해보자.
class Ex12_3 {
public static void main(String[] args) {
Box b = null;
Box<String> bStr = null;
b = (Box)bStr; //Box<String> -> Box 가능 But 경고
bStr = (Box<String>)b; //Box -> Box<String> 가능 But 경고
} // main
}
여기서 ①`Box b = new Box<String>();`가 가능하다. 원시타입으로 제네릭타입을 가리키는 게 가능하다.
원래는 ② `Box<String> b = new Box<String>();`으로 써야한다. 그런데 ①이 가능하다는 것은
③ `Box b = (Box)new Box<String>();`으로 Box가 생략되었다는 것이다. 그런데 ①로 적는다면,
`b.add(new Integer(100));`이 경고는 나오지만 가능해진다. 왜냐하면 참조변수가 원시타입이기 때문이다.
그래서 다 들어가는 것이다.
그래서 원시타입과 제네릭 타입을 섞어서 쓰면 안 된다.
Box<Object> objBox = null;
Box<String> strBox = null;
objBox = (Box<Object>)strBox; //에러. Box<String> -> Box<Object>
strBox = (Box<Object>)objBox; //에러. Box<Object> -> Box<String>
서로 다른 타입이 대입된 제네릭 타입끼리는 형변환이 안 된다.
- 와일드 카드가 사용된 제네릭 타입으로는 형변환 가능
Box<Object> objBox = Box<Object>new Box<String>(); //에러. 형변환 불가능
Box<? extends Object> wBox = (Box<? extends Object>)new Box<String>(); //OK
Box<? extends Object> wBox = new Box<String>(); //위 문장과 동일. 위 문장의 ()가 생략된 것
// 매개변수로 FruitBox<Fruit>, FruitBox<Apple>, FruitBox<Grape> 등이 가능
static Juice makeJuice(FruitBox<? extends Fruit> box) { ... }
FruitBox<? extends Fruit> box = new FruitBox<Fruit>(); //OK
FruitBox<? extends Fruit> box = new FruitBox<Apple>(); //OK
class Ex12_3 {
public static void main(String[] args) {
FruitBox<Fruit> fbox = new FruitBox<Fruit>(); //OK
FruitBox<Apple> abox = new FruitBox<Apple>(); //OK
FruitBox<? extends Fruit> wfbox = new FruitBox<Fruit>(); //OK
// FruitBox<? extends Fruit> wfbox = (FruitBox<? extends Fruit>)new FruitBox<Fruit>(); //OK
//FruitBox<Apple> -> FruitBox<? extends Fruit>
FruitBox<? extends Fruit> wabox = new FruitBox<Apple>(); //OK
//FruitBox<? extends Fruit> -> FruitBox<Apple> 가능?
FruitBox<Apple> appleBox = (FruitBox<Apple>) wabox; //OK. 경고 발생
} // main
}
① `FruitBox<? extends Fruit> wfbox = new FruitBox<Fruit>();`
② `FruitBox<? extends Fruit> wfbox = (FruitBox<? extends Fruit>)new FruitBox<Fruit>();`
①은 좌변과 우변이 타입불일치하다. 그렇기 때문에 형변환이 필요하다. 그래서 원래는 ②와 같이 되어야 하는데 생략이 된 것이다.
2. 제네릭 타입의 제거
- 컴파일러는 제네릭 타입을 제거하고, 필요한 곳에 형변환을 넣는다.
① 제네릭 타입의 경계(bound)를 제거
컴파일러가 1-> 2로 바꾼다.
그래서 1에서 그냥 T였으면 2에서 Object로 바뀐다.
그런데 사진에서는 Fruit의 자손인 T로 되어있다. 그래서 2에서 Fruit으로 바뀌는 것이다.
즉, 기본적으로 타입T는 Object로 바뀐다. 그런데 제한된 경우에는 Object가 아닌 제한된 타입으로 바뀐다.
② 제네릭 타입 제거 후에 타입이 불일치하면, 형변환을 추가
형변환을 생략한다고 해서 안 하는 것이 아니라 컴파일러가 대신 해주는 것.
③ 와일드 카드가 포함된 경우, 적절한 타입으로 형변환 추가
출처
'🎥Back > 자바의 정석' 카테고리의 다른 글
[JAVA의 정석] 프로그램오류. try-catch (0) | 2024.02.18 |
---|---|
[JAVA의 정석]열거형 (0) | 2024.01.19 |
[JAVA의 정석]와일드카드, 제네릭 메서드 (0) | 2024.01.19 |
[JAVA의 정석]Generics, Generics 클래스 (0) | 2024.01.18 |
[JAVA의 정석]Collections 클래스, 컬렉션 클래스 요약 (2) | 2024.01.17 |