2015-09-07 7 views
7

Ho letto che da Java 7, la creazione di Raccolte con la specifica del tipo sul lato destro come nella prima istruzione è di cattivo stile perché il compilatore può inferire il tipo dal lato sinistro.Perché il tipo non viene dedotto quando si lascia l'operatore generici

List<Integer> myList = new ArrayList<Integer>(); 

La mia domanda è quando si inizializza la lista in questo modo, il compilatore non trova il tipo e ottengo un tipo di avvertimento incontrollato:

List<Integer> myList = new ArrayList(); 

risposta

12

il compilatore non inferire il tipo, perché si sta un'istanza di un grezzoArrayList. Ma è abbastanza intelligente da avvertirti che potrebbero esserci problemi quando si lavora con questo oggetto (grezzo).

Vale la pena menzionare il motivo di questo avviso. A causa dello type erasure, le informazioni parametriche (<Integer>) relative allo List verranno completamente eliminate in fase di runtime, quando la variabile contiene elementi di tipo Object. Considerare questo frammento:

List rawList = new ArrayList(); //raw list 
rawList.add(new String("hello")); 
rawList.add(new Double(12.3d)); 
List<Integer> intList = rawList; // warning! 

Questo frammento verrà compilato, ma genererà alcuni avvisi. Avendo un elenco non elaborato (rawList), puoi aggiungere qualsiasi tipo non primitivo all'elenco, incluso String, Double, ecc. Ma quando assegni questa raccolta a un elenco, che è specificato per contenere gli interi solo, allora questo è un problema. In Runtime riceverai un ClassCastException quando proverai a recuperare alcuni elementi dallo intList, che dovrebbe essere un Integer, ma in realtà è un String o altro.

Breve storia - non mescolare i tipi non elaborati con Generics!

Nel tuo caso, il compilatore sarebbe forse hanno dedotto il tipo, se si è utilizzato il diamante:

List<Integer> list = new ArrayList<>(); //¯\_(ツ)_/¯ 
            ↑↑ 
9

Perché avete dimenticato le parentesi angolari (chiamato operatore di diamante).

List<Integer> myList = new ArrayList<>(); 

Questo è sintatticamente equivalente a

List<Integer> myList = new ArrayList<Integer>(); 

ma diverso da

List<Integer> myList = new ArrayList(); 

Nel 3 ° stai dicendo che il lato destro è un tipo grezzo che significa l'ArrayList può contenere tutti gli oggetti (non solo intero). I generici sono solo in fase di compilazione e sono compilati in tipi di salvataggio.

+0

Perché questo danno al compilatore più informazioni rispetto Lista myList = new ArrayList() in quanto sul lato sinistro le informazioni generiche è availabe – PKuhn

+0

Perché entrambi sono semanticamente differenti. Omettere il tipo nel diamante è solo un suggerimento sintattico. – lschuetze

2

È possibile utilizzare operatore di diamante di dedurre il tipo di dichiarazione, come specificato nella JLS (§15.9),.

Un'espressione creazione istanza di classe specifica una classe istanziare, eventualmente seguito da argomenti di tipo (§4.5.1) o un diamante ("<>") se la classe essendo istanziata è generica (§8.1.2), seguito da un elenco (eventualmente vuoto) di argomenti con valore reale per il costruttore.

List<Integer> myList = new ArrayList<>(); 
Problemi correlati