2014-06-19 20 views
11

Per di codice seguente:generici Java: assegnazione con jolly nidificata Parametri

public static class Abc<X> { } 
public static class Def<Y> { } 
public static class Ghi<Z> { } 

public void doThis() { 
    List<?> listOne; 
    List<Abc<?>> listTwo; 
    List<Abc<Def<?>>> listThree; 
    List<Abc<Def<Ghi<?>>>> listFour; 
    List<Abc<Def<Ghi<String>>>> listFive; 

    Abc<Def<Ghi<String>>> abcdef; 

    abcdef = new Abc<Def<Ghi<String>>>(); 

    listOne.add(abcdef); // line 1 
    listTwo.add(abcdef); // line 2 
    listThree.add(abcdef); // line 3 
    listFour.add(abcdef); // line 4 
    listFive.add(abcdef); // line 5 
} 

linee 1, 3, e 4 non compilare:

(line 1)

The method add(capture#1-of ?) in the type List<capture#1-of ?> is not applicable for the arguments (Abc<Def<Ghi<String>>>) 

(riga 3)

The method add(Abc<Def<?>>) in the type List<Abc<Def<?>>> is not applicable for the arguments (Abc<Def<Ghi<String>>>) 

(linea 4)

The method add(Abc<Def<Ghi<?>>>) in the type List<Abc<Def<Ghi<?>>>> is not applicable for the arguments (Abc<Def<Ghi<String>>>) 

linee 2 e 5, tuttavia, la compilazione.

Qualcuno potrebbe spiegare perché le righe 1, 3 e 4 non sono assegnazioni legali? E se i parametri jolly non possono essere utilizzati in quel modo su quelle linee, allora perché l'assegnazione sulla linea 2 è legale?

+0

Davvero una buona domanda! Per * linea 1 *, è perché non è possibile aggiungere nulla a un elenco di tipi sconosciuti ad eccezione di 'null'. – rlegendi

risposta

7

listOne.add(abcdef) (riga 1) non valido perché List<?> rappresenta un elenco di alcuni tipi specifici sconosciuti. Ad esempio, potrebbe essere un List<String>, quindi non vorremmo aggiungere nulla che non sia un String. L'errore del compilatore si verifica perché Abc<Def<Ghi<String>>> non è assegnabile a ?.

listTwo.add(abcdef) (linea 2) è valida perché List<Abc<?>> rappresenta un elenco di Abc s di qualsiasi tipo. Proprio così - nested i caratteri jolly sono diversi dai caratteri jolly di livello superiore in quanto rappresentano qualsiasi tipo piuttosto che un tipo specifico (in altre parole, i caratteri jolly nidificati non sono capture). Il compilatore lo consente perché Abc<Def<Ghi<String>>> è assegnabile a Abc<?>. Vedi questo post per ulteriori discussioni di caratteri jolly annidati: Multiple wildcards on a generic methods makes Java compiler (and me!) very confused

listThree.add(abcdef) (linea 3) non è valido perché List<Abc<Def<?>>> rappresenta una lista di Abc s di Def s di qualsiasi tipo. I generici non sono covarianti, quindi Abc<Def<Ghi<String>>> non è assegnabile a Abc<Def<?>>, anche se Def<Ghi<String>> è assegnabile a Def<?>. A List<Integer> non è assegnabile a List<Number> per lo stesso motivo. Vedi questo post per ulteriori spiegazioni: Is List<Dog> a subclass of List<Animal>? Why aren't Java's generics implicitly polymorphic?

listFour.add(abcdef) (linea 4) non è valida per la stessa ragione - Abc<Def<Ghi<String>>> non è cedibile a Abc<Def<Ghi<?>>>.

listFive.add(abcdef) (riga 5) è valido perché i tipi generici corrispondono esattamente - Abc<Def<Ghi<String>>> è ovviamente assegnabile a Abc<Def<Ghi<String>>>.

+3

Volevo seguire che i problemi di assegnazione delle righe 3 e 4 possono essere risolti cambiando le dichiarazioni da 'Lista >> listaTre' a' Elenco >> listThree' e da 'Elenco >>>' a 'Elenco >>> listFour'. Grazie per la spiegazione concisa e link utili; è molto più chiaro ora. – Sumitsu