Domanda

L'operatore diamante in Java 7 permette codice come il seguente:

List<String> list = new LinkedList<>();

Tuttavia in Java 5/6, posso scrivere semplicemente:

List<String> list = new LinkedList();

La mia comprensione di tipo cancellazione è che questi sono esattamente gli stessi. (Il generico viene rimosso in fase di esecuzione in ogni caso).

Perché perdere tempo con il diamante a tutti? Quali sono le nuove funzionalità di sicurezza / tipo vuol permettere? Se non produce alcuna nuova funzionalità perchè hanno lo menzionano come una caratteristica? È la mia comprensione di questo concetto viziata?

È stato utile?

Soluzione

Il problema con

List<String> list = new LinkedList();

è che sul lato sinistro, si utilizza il generici tipo List<String> dove sul lato destro si utilizza il raw tipo LinkedList. tipi prime in Java in modo efficace esistono solo per la compatibilità con il codice pre-generici e non dovrebbero mai essere utilizzati in nuovo codice a meno che è assolutamente necessario.

Ora, se Java avuto generici fin dall'inizio e non ha avuto tipi, come LinkedList, che sono stati originariamente creati prima che avesse generici, probabilmente avrebbe potuto fare in modo che il costruttore per un tipo generico deduce automaticamente il suo tipo parametri dal lato sinistro della cessione se possibile. Ma non ha fatto, e deve trattare i tipi prime e tipi generici in modo diverso per la compatibilità all'indietro. Che le foglie li bisogno di fare un leggermente diverso , ma altrettanto comoda, di modo che dichiara una nuova istanza di un oggetto generico senza dover ripetere i suoi parametri di tipo ... l'operatore diamante.

Per quanto riguarda il tuo esempio originale di List<String> list = new LinkedList(), il compilatore genera un avviso per questo incarico perché deve. Considerate questo:

List<String> strings = ... // some list that contains some strings

// Totally legal since you used the raw type and lost all type checking!
List<Integer> integers = new LinkedList(strings);

Generics esistono per fornire protezione in fase di compilazione contro fare la cosa sbagliata. Nell'esempio di cui sopra, utilizzando il tipo grezzo significa che non si ottiene questa protezione e otterrà un errore in fase di esecuzione. Questo è il motivo per cui non si dovrebbe usare tipi prime.

// Not legal since the right side is actually generic!
List<Integer> integers = new LinkedList<>(strings);

L'operatore diamante, tuttavia, permette il lato destro della assegnazione da definire come un vero esempio generico con gli stessi parametri di tipo come il lato sinistro ... senza dover digitare nuovamente tali parametri. Esso consente di mantenere la sicurezza dei farmaci generici con quasi lo stesso sforzo di utilizzare il tipo di prima.

Penso che la cosa fondamentale da capire è che i tipi di grezzi (senza <>) non possono essere trattati come tipi generici. Quando si dichiara un tipo grezzo, si ottiene nessuno dei benefici e controllo dei tipi di farmaci generici. Dovete anche tenere a mente che generici sono una parte generale scopo del linguaggio Java ... non vale solo per i costruttori no-arg di Collections!

Altri suggerimenti

La vostra comprensione è leggermente imperfetto. L'operatore diamante è una bella caratteristica come lei non c'è bisogno di ripetere se stessi. Ha senso per definire il tipo, una volta quando si dichiara il tipo, ma semplicemente non ha senso definire di nuovo sul lato destro. Il principio DRY.

Ora, per spiegare tutti i fuzz sulla definizione dei tipi. Hai ragione che il tipo viene rimosso in fase di esecuzione, ma una volta che si desidera recuperare qualcosa di un elenco con definizione di tipo si ottiene indietro come il tipo che avete definito quando si dichiara l'elenco altrimenti perderebbe tutte le caratteristiche specifiche e hanno solo la oggetto caratteristiche tranne quando ci si lanci l'oggetto recuperato al suo tipo originale che a volte può essere molto difficile e il risultato in un ClassCastException.

Utilizzando List<String> list = new LinkedList() si arriva rawtype avvertimenti.

Questa riga fa sì che il [incontrollato] avvertimento:

List<String> list = new LinkedList();

Quindi, le trasformazioni domanda: perché [incontrollato] avvertimento non viene soppressa automaticamente solo per il caso in cui si crea nuova collezione

Credo, sarebbe molto più difficile compito quindi l'aggiunta di funzionalità di <>.

UPD :. Penso anche che ci sarebbe stato un disastro se fosse legalmente utilizzare tipi prime 'solo per un paio di cose'

In teoria, l'operatore diamante consente di scrivere codice più compatto (e leggibile) salvando argomenti di tipo ripetuti. In pratica, si tratta di appena due confondendo caratteri più dando nulla. Perché?

  1. Nessun sano di mente programmatore utilizza tipi di prime in nuovo codice. Quindi il compilatore potrebbe semplicemente supporre che scrivendo senza argomenti tipo che si desidera a dedurre loro.
  2. L'operatore diamante non fornisce informazioni sul tipo, si dice solo il compilatore, "andrà tutto bene". Così omettendo che si può fare nulla di male. In ogni luogo in cui l'operatore diamante è legale che potrebbe essere "dedurre" dal compilatore.

IMHO, avendo un modo chiaro e semplice per marcare una fonte come Java 7 sarebbe più utile che inventare cose strane. Nel codice in modo marcato i tipi prime potrebbero essere proibite senza perdere nulla.

Btw., Non credo che dovrebbe essere fatto utilizzando uno switch di compilazione. La versione Java di un file di programma è un attributo del file, nessuna opzione a tutti. Usando qualcosa di così banale come

package 7 com.example;

potrebbe mettere in chiaro (si può preferire qualcosa di più sofisticato tra cui una o più parole chiave di fantasia). Sarebbe anche permettere di compilare fonti scritte per le diverse versioni di Java insieme senza problemi. Essa consentirebbe l'introduzione di nuove parole chiave (ad esempio, "modulo") o l'eliminazione di alcune funzioni obsolete (più classi non pubbliche non nidificati in un singolo file o di sorta) senza perdere la compatibilità.

Quando si scrive List<String> list = new LinkedList();, compilatore genera un avviso "incontrollato". Si può ignorarlo, ma se è stato utilizzato per ignorare questi avvertimenti si può anche perdere un avviso che li informa circa un problema di sicurezza di tipo reale.

Quindi, è meglio scrivere un codice che non genera avvisi aggiuntivi, e l'operatore diamante permette di farlo in modo conveniente, senza inutili ripetizioni.

Tutti detto in altre risposte sono validi, ma i casi di utilizzo non sono del tutto IMHO validi. Se uno dei controlli fuori Guava e soprattutto la roba correlata collezioni, lo stesso è stato fatto con metodi statici. Per esempio. Lists.newArrayList () che consente di scrivere

List<String> names = Lists.newArrayList();

o con l'importazione static

import static com.google.common.collect.Lists.*;
...
List<String> names = newArrayList();
List<String> names = newArrayList("one", "two", "three");

Guava ha altre caratteristiche molto potenti come questo e io in realtà non riesco a pensare a molto usi per il <>.

Sarebbe stato più utile se ne è andato per rendere il comportamento dell'operatore diamante il default, che è, il tipo è inferenced dal lato sinistro della espressione o se il tipo del lato sinistro è stato inferenced dal lato destro. Quest'ultimo è ciò che accade in Scala.

Il punto per l'operatore diamante è semplicemente quello di ridurre digitazione di codice quando si dichiara tipi generici. Essa non ha alcun effetto su qualunque fase di esecuzione.

L'unica differenza se si specifica in Java 5 e 6,

List<String> list = new ArrayList();

è che è necessario specificare @SuppressWarnings("unchecked") al list (altrimenti si otterrà un avvertimento getto incontrollato). La mia comprensione è che operatore diamante sta cercando di rendere lo sviluppo più facile. Non ha niente a che fare in esecuzione runtime di farmaci generici a tutti.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top