Java i wymazywanie typów

0

Witam
Zastanawia mnie jedna kwestia w typach generycznych Javy. Mam taki kod:


interface A {
    void metoda();
}

class B<T> {
     void set() {
        T a = (T)new Object();
    }
}

public class Main {

    public static void main(String[] args) {
        B<A> b = new B<A>();
        b.set();
    }

Ponieważ w czasie kompilacji T zostaje przekształcone do Object ta linijka: T a = (T)new Object(); powoduje zrzutowanie Object do Object a więc wszystko działa bez zarzutu. Jednak gdy definicje klasy zmienie w taki sposób:
class B<T extends A> to dostaje wyjątek ClassCastException. Dla mnie jest to zastanawiające bo skoro Java zamarze typ A do Object to znowu ten kod nie powinien powodować problemów. Jedyne wytłumaczenie jakie przychodzi mi do głowy to to że w przypadku extends typ nie jest zamazywany do Object tylko do typu A. Czy ktoś może potwierdzić to przepuszczenie ?

0

Potwierdzam ;) Typy generyczne zadeklarowane jako dziedziczace po jakims typie ('extends') sa wymazywane do tego typu, a nie do Object (dotyczy to oczywiscie tylko 'samodzielnych' referencji do generycznego typu, jakie uzywamy w kodzie, wszelkie parametryzowane klasy sa wymazywane do jednej i tej samej klasy operujacej na Object). Mozna to latwo sprawdzic:

public class Test {
static interface InnerFace1 {}
static interface InnerFace2 {}
static interface InnerFace3 {}

public <S extends InnerFace1> void doSth(S s) {}
public <T extends InnerFace2> void doSth(T t) {}
public <U extends InnerFace3> void doSth(U u) {}
}

Powyzsze powinno skompilowac sie bez problemu do 3 przeladowanych metod (choc nie sprawdzalem, moze byc literowka;)

Ciekawie robi sie, gdy uzywamy tzw. 'type intersection', czyli extends po wielu interfejsach. Okazuje sie, ze typ genryczny wymazywany jest do pierwszego w kolejnosci zadeklarowanego typu bazowego, czyli:

public class Test {
static interface InnerFace1 {}
static interface InnerFace2 {}
static interface InnerFace3 {}

public <S extends InnerFace1 & InnerFace2> void doSth(S s) {}
public <T extends InnerFace3 & InnerFace1> void doSth(T t) {}

}

sie skompiluje, ale juz:

public class Test {
static interface InnerFace1 {}
static interface InnerFace2 {}
static interface InnerFace3 {}

public <S extends InnerFace1 & InnerFace2> void doSth(S s) {}
public <T extends InnerFace1 & InnerFace3> void doSth(T t) {}

}

nie daje rady. Nic tylko walic glowa w 'wall of erasure' [glowa] </u>

0

Kordzik, dzięki za wyjaśnienie :)

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.