2016-07-18 119 views
5

Supponiamo di avere un pacchetto di classe generico e un metodo generico di consegna mostrato nel codice sottostante. Il metodo stampa e restituisce x a cui è assegnato un parametro di tipo intero all'interno del metodo.Non digita il parametro nessun ruolo?

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

All'interno del sistema principale chiamo il metodo di consegna passando un parametro di tipo Parcel. Tuttavia esso stampa ancora 100.

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

Ciò consegue che il tipo di argomento Parcel passato nella linea di stampa non gioca alcun ruolo, e mi aspettavo un'eccezione qui. Come funziona ?

+5

Poiché si sta vincolando a 'java.lang.Object'. 'X' non è associato a nessun tipo particolare assumendo che il suo limite superiore sia' java.lang.Object', quindi non esiste 'ClassCastException'. Ne riceverai uno, se invochi "consegna" e lanci il risultato a una variabile/campo/parametro che hanno altri tipi di 'java.lang.Object',' java.lang.Number' e 'java.lang. Integer'. E il tuo codice non fallisce perché invochi 'println (Object)'. Se lo si cambia in 'pacco. deliver() ', il compilatore userà' println (String) 'che risulterà in' java.lang.Integer non può essere lanciato su java.lang.String' –

+1

Inoltre, è possibile modificare il vincolo '' a un altro tipo concreto, e il compilatore userà cast di tipo conrete nel metodo 'deliver()'. Supponiamo che '' risulterebbe in 'ClassCastException' per questa riga:' X x = (X) (Object) new Integer (100); 'perché' X' viene sostituito con 'java.lang.String' Qui. –

risposta

1

Quello che si osserva è chiamato type erasure. I parametri generici vengono utilizzati dal compilatore per garantire la correttezza del tipo e non sono presenti in fase di esecuzione.

In generale nulla vi impedisce di fare questo trucco:

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

In realtà la mia risposta originale a volte è stato per questo Parcel implementazione

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

Ma l'idea chiave è lo stesso per <X> X deliver():

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