2014-06-20 16 views
7

Prima di Java 7 la sintassi di seguito è stato utilizzato per creare un ArrayList,Utilizzando operatore diamante in Java 7

ArrayList<Integer> ints = new ArrayList<Integer>(Arrays.asList(1,2,3,4,5,6,7)); 

Ma dal momento che Java 7 possiamo omettere il tipo generico nel cioè costruttore,

ArrayList<Integer> ints = new ArrayList<>(Arrays.asList(1,2,3,4,5,6,7)); 

ma quando ho provato a fare qualcosa di simile,

ArrayList<Number> nums = new ArrayList<>(Arrays.asList(1,2,3,4,4,5.5,6.6,7.7)); 

ottengo un errore, ma quando ho citato il tipo generico sul lato destro vale a dire,

ArrayList<Number> nums = new ArrayList<Number>(Arrays.asList(1,2,3,4,5.5,6.6,7.7)); 

Il codice funziona perfettamente. Quale potrebbe essere la ragione di questo?

Grazie in anticipo.

+0

Non riesco a richiamare specifici passaggi dal JLS che sono cambiati tra Java 7 e 8 per supportare questo, quindi questo è un commento, ma se la memoria serve Java 8 espanso i tipi di inferenza che potrebbero essere eseguiti, credo permettendo di cercare anche i supertipi e/o tenendo conto del contesto aggiuntivo. Il tuo terzo snippet di codice viene compilato senza lamentarsi in Java 8. – awksp

risposta

4

Arrays.asList è un metodo generico, così tecnicamente, può essere richiamato come:

Arrays.<Number> asList(1, 2, 3); 

Anche prima Java 7, la lingua potrebbe fare qualche inferenza limitato per eliminare questo quando il lato sinistro era noto, come in

final List<Number> nums = Arrays.asList(1, 2, 3); 

sembra che inciampato su un caso limite in cui i due tipi di inferenza non possono essere combinati con successo, in cui l'inferenza di diamante e il metodo di inferenza generiche non vanno d'accordo. Sono sicuro che anche the JLS sheds more light on this se lo scavassi.

3

I generici Java sono invarianti mentre gli array sono covarianti.

Se generici in Java sono stati covariante, se A è un sottotipo di B, poi List[A] è un sottotipo di List[B]. Ma non è il caso in Java. (Scala dispone di un'implementazione di covarianza. In Scala, se B estende A, quindi List[B] estende List[A])

Ma String[] è sottotipo di Object[]

Quindi un ArrayList<Double> non possono essere gettati a un ArrayList<Number> come nel tuo caso.