충분히 쌓여가는
지네릭 형변환 본문
지네릭 타입의 형변환
지네릭 타입과 원시 타입 간의 형변환은 바람직 하지 않다(경고 발생)
Box<Object> objBox = null;
Box box = (Box)objBox; // OK, 지네릭 타입 -> 원시 타입, 경고 발생
objBox = (Box<Object>)box; // OK, 원시 타입 -> 지네릭 타입, 경고 발생
코드
import java.util.ArrayList;
class Fruit implements Eatable {
public String toString() { return "Fruit";}
}
class Apple extends Fruit { public String toString() { return "Apple";}}
class Grape extends Fruit { public String toString() { return "Grape";}}
class Toy { public String toString() { return "Toy" ;}}
interface Eatable {}
class GenericesTypeCastingTest {
public static void main(String[] args) {
Box b = null;
Box<String> bStr = null;
b = (Box)bStr; // Box<String> -> Box, 가능하지만 경고
bStr = (Box<String>)b; // Box -> Box<String>, 가능하지만 경고
}
}
class FruitBox<T extends Fruit & Eatable> extends Box<T> {}
class Box<T> {
ArrayList<T> list = new ArrayList<T>();
void add(T item) { list.add(item); }
T get(int i) { return list.get(i); }
int size() { return list.size(); }
public String toString() { return list.toString();}
}
서로 다른 타입이 대입된 지네릭 타입들끼리는 형변환 불가능
Box<Object> objBox = null;
Box<String> strBox = null;
objBox(Box<Object>)strBox; // 에러, Box<String>가 Box<Object>는 안됨
strBox(Box<String>)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>(); // 위 문장과 동일, (Box<? extends Object>) 생략됨
// 매개변수로 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
코드
import java.util.ArrayList;
class Fruit implements Eatable {
public String toString() { return "Fruit";}
}
class Apple extends Fruit { public String toString() { return "Apple";}}
class Grape extends Fruit { public String toString() { return "Grape";}}
class Toy { public String toString() { return "Toy" ;}}
interface Eatable {}
class GenericesTypeCastingTest {
public static void main(String[] args) {
FruitBox<? extends Fruit> fBox = (FruitBox<? extends Fruit>)new FruitBox<Fruit>();
// FruitBox<Apple> -> FruitBox<? extends Fruit> 가능
FruitBox<? extends Fruit> aBox = new FruitBox<Apple>();
// FruitBox<? extends Fruit> -> FruitBox<Apple> 가능
FruitBox<Apple> appleBox = (FruitBox<Apple>)aBox; // OK, 경고발생
}
}
class FruitBox<T extends Fruit & Eatable> extends Box<T> {}
class Box<T> {
ArrayList<T> list = new ArrayList<T>();
void add(T item) { list.add(item); }
T get(int i) { return list.get(i); }
int size() { return list.size(); }
public String toString() { return list.toString();}
}
지네릭 타입의 제거
컴파일러는 지네릭 타입을 제거하고, 필요한 곳에 형변환을 넣는다
① 지네릭 타입의 경계(bound)를 제거
<T>일 경우: Object 대신 타입변수 <T>를 사용해도 컴파일하면 <T>가 Object로 바뀐다 -> 하위호환성 때문에 그렇다(컴파일 때 지네릭 타입 유지X)
그림에서는 <T extends Fruit>이기 때문에 T는 Fruit과 Fruit의 자손들이어야 한다, 따라서 void add(Object t)가 아니라 void add(Fruit t)이다
[기본적인 경우 <T>가 Object로 바뀌는데, 제한된 경우 그림처럼 <T>가 제한된 타입 Fruit로 바뀐다]
② 지네릭 타입 제거 후에 타입이 불일치하면, 형변환을 추가
③ 와일드 카드가 포함된 경우, 적절한 타입으로 형변환 추가
'Java > JAVA3' 카테고리의 다른 글
열거형에 멤버 추가하기 (0) | 2023.07.31 |
---|---|
열거형(enum) (0) | 2023.07.30 |
지네릭 메서드 (0) | 2023.07.28 |
와일드 카드 <?>, 지네릭 메서드 (0) | 2023.07.28 |
제한된 지네릭 클래스, 지네릭스의 제약 (0) | 2023.07.27 |