Notice
Recent Posts
Recent Comments
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
Archives
Today
Total
관리 메뉴

충분히 쌓여가는

지네릭 형변환 본문

Java/JAVA3

지네릭 형변환

빌드이너프 2023. 7. 29. 14:54

지네릭 타입의 형변환

지네릭 타입과 원시 타입 간의 형변환은 바람직 하지 않다(경고 발생)

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