2016-07-18 10 views
5

Załóżmy, że mam paczkę klasy ogólnej i metodę ogólną dostarczaną w poniższym kodzie. Metoda drukuje i zwraca x, któremu przypisano parametr typu Integer w metodzie.Czy typ parametru nie odgrywa żadnej roli?

public class Parcel<T> { 
    public <X> X deliver(){ 
     X x = (X) new Integer(100); 
     System.out.println(x); 
     return x; 
    } 
} 

Wewnątrz głównej wywołać metodę dostarczyć, przekazując parametr typu Parcel. Jednak nadal drukuje 100.

public static void main(String args[]) { 
    Parcel<String> parcel = new Parcel<>(); 
    System.out.println(parcel.<Parcel> deliver()); 
} 

Wynika to, że rodzaj argumentu działki przekazywane w linii wydruku nie odgrywa żadnej roli, a ja spodziewałem wyjątek tutaj. Jak to działa ?

+5

Ponieważ wiążisz do 'java.lang.Object'. 'X' nie jest związany z żadnym określonym typem przy założeniu, że jego górna granica to' java.lang.Object', więc nie ma 'ClassCastException'. Dostaniesz jeden, jeśli wywołasz 'dostarczyć' i rzucisz wynik do zmiennej/field/parameter, która ma inne typy niż' java.lang.Object', 'java.lang.Number' i' java.lang. Integer'. Twój kod nie zawiedzie, ponieważ wywołujesz 'println (Object)'. Jeśli zmienisz go na 'działka. dostarczyć() ', kompilator użyje' println (String) ', który spowoduje, że' java.lang.Integer nie będzie można przesłać do java.lang.String' –

+1

Możesz także zmienić ograniczenie '', aby uzyskać więcej konkretny typ, a kompilator użyje typu conrete w metodzie 'dostawa()'. Powiedz: '' powodowałoby 'ClassCastException' dla tej linii:' X x = (X) (Object) new Integer (100); 'ponieważ' X' jest zamieniane na 'java.lang.String' tutaj. –

Odpowiedz

1

To, co obserwujesz, nazywa się type erasure. Parametry ogólne są używane przez kompilator w celu zapewnienia poprawności typu i nie występują w czasie wykonywania.

Generalnie nic nie stoi na przeszkodzie temu ten trick:

List<Integer> list = new ArrayList<>(); 
list.append(""); // produces compiler error 

// just drop that "useless" generic argument 
List erased = (List) list; 
erased.append(""); // works fine 

EDIT

Właściwie mój oryginalny odpowiedź czasami był do tego Parcel realizacji

public class Parcel<T> { 
    public T deliver(){ 
     T x = (T) new Integer(100); 
     System.out.println(x); 
     return x; 
    } 
} 

ale kluczem idea jest to samo dla <X> X deliver():

Object parcel = parcel.<Parcel> deliver(); // erased, works ok 
Parcel parcel = parcel.<Parcel> deliver(); // java.lang.ClassCastException 
Powiązane problemy