2015-09-16 15 views
6

Nel seguente codice Java, ho creato un elenco nums. Posso assegnare l'altra lista durante la dichiarazione. Ma non è possibile aggiungere nuovi articoli tranne lo null. Quindi, significa che lo nums è di sola lettura? Perché? È possibile aggiungere nuovi elementi in quella lista?"? Extends ParentClass" rende di sola lettura?

List<Integer> ints = new ArrayList<Integer>(); 
ints.add(1); 
ints.add(2); 

List<? extends Number> nums = ints; 
nums.add(3.14); //Generates error 
nums.addAll(ints); //Generates error 

nums.add(null);  //works 
System.out.println(nums.get(0)); //works 

Ho passato con questo link. Non riesco a ottenere la ragione esatta.

+0

Non so, nota che nums.add ((Numero) new Double (3.14)); genera l'errore: Il metodo add (cattura n. 1 di? estende Numero) nel tipo Lista non è applicabile per gli argomenti (numero) –

+1

Vedere questa domanda: http://stackoverflow.com/questions/2723397/java-generics-what-is-pecs – Natix

+0

questo è un malinteso molto comune; ma la concezione funziona nella maggior parte dei casi :) – ZhongYu

risposta

5

Is it possible to add new items in that list?

No ... perché quel codice non sa cosa sia "effettivamente" un elenco di. Immaginate se si potesse :

List<String> strings = new ArrayList<>(); 
List<? extends Object> objects = strings; // This is fine 
objects.add(new Object()); // Fortunately this *isn't* valid... 
System.out.println(strings.get(0).length()); // Or what would this do? 

In sostanza, quando si utilizza un carattere jolly come ? extends T si può ottenere solo valori fuori tramite l'API ... e quando si utilizza un carattere jolly come ? super T, si può mettere solo i valori in tramite l'API - perché questo è ciò che è sicuro.

+0

quindi, possiamo dire che la lista diventerà di sola lettura? –

+4

@PradipKharbuja: No, non proprio. La lista stessa non è di sola lettura: è comunque possibile aggiungerla tramite 'ints', o rimuoverla da essa tramite' nums'. Non è possibile * aggiungere * a 'nums' a causa della sicurezza del tipo. –

-1

Generics è solo tempo di compilazione.

Quindi il compilatore deciderà qual è il tipo effettivo che verrà utilizzato.

List<? extends Number> 

Significa che non siamo sicuri del tipo effettivo dell'oggetto.

Quindi il compilatore non si assicura quale sia il tipo effettivo dell'elenco.

2

No, non è di sola lettura ... anche se in genere è l'intenzione.

Dato un oggetto List<? extends Number>, il compilatore converts il suo tipo su List<X> dove X è un sottotipo sconosciuto di Numero. Pertanto, l'oggetto ha un metodo add(X). Possiamo chiamare il metodo con un argomento X ... ad esempio, null.

E poiché get() rendimenti X, potremmo anche chiamare add() con un valore da get() .... Direttamente invocando list.add(list.get(i)) non funziona, anche se ha un senso. Avremo bisogno di un po 'di helper.

L'esempio classico è Collections.reverse(List<? extends Object> list). Questo metodo modificherà lo list, nonostante il carattere jolly.

È inoltre possibile chiamare i metodi di modifica come clear(), ovviamente in qualsiasi elenco.


Detto, jolly è infatti principalmente per uso loco variance, e più spesso, esso trasmette l'intenzione da parte del progettista API se un tipo di parametro è destinato in o fuori. Ad esempio, dichiarando List<? super/extends Foo>, l'API esprime che intende immettere in oppure ottenere T di, l'elenco.

È un equivoco che il jolly effettui la lettura/la sola scrittura. Ma questo malinteso funziona nella maggior parte dei casi d'uso. E più persone che hanno questa idea sbagliata, più diventa una convenzione ...

vedere il mio articolo sul jolly - http://bayou.io/draft/Capturing_Wildcards.html

0

E 'aiuta quando si pensa di List<? extends Number> nums come List di un certo tipo di cosa che si estende Number , ma non puoi essere sicuro di cosa. Come tale, tutto ciò che fai con nums deve essere in grado di fare una cosa del genere.

L'aggiunta di null funziona perché null può essere inserito in assolutamente nulla. Tutto il resto che proverai ad aggiungere fallirà, perché il compilatore non può essere sicuro al 100% che la cosa che stai aggiungendo estende la cosa di cui è fatto l'elenco.

Invece di List<? extends Number> nums do List<Number> nums, perché è ancora possibile inserire qualsiasi cosa che si estende Number.

? non significa "nulla", è più vicino al significato di "specifico ma sconosciuto".