Mi sono imbattuto in alcuni, almeno per me, strano comportamento in Eclipse 4.4 e Java 8 build 45 durante l'esecuzione di un refactoring di espressioni di estrazione. L'esempio seguente mostra il codice originale e senza errori prima di applicare la refactoring estratto:Tipo mancata corrispondenza dopo l'estrazione di un'espressione con tipo di ritorno generico
import java.util.Map;
import java.util.Set;
public class MyMap<K, V> {
public void putAll(final Map<? extends K, ? extends V> mapToCopy) {
for (Map.Entry<? extends K, ? extends V> entry : mapToCopy.entrySet()) {
}
}
}
Il risultato del refactoring Eclipse assomiglia a questo e porta alla seguente messaggio di errore che fa riferimento al l'accesso in lettura di entrySet
nel dichiarazione ciclo:
public void putAll(final Map<? extends K, ? extends V> mapToCopy) {
Set<?> entrySet = mapToCopy.entrySet();
for (Map.Entry<? extends K, ? extends V> entry : entrySet) {
^^^^^^^^
}
}
Type mismatch: cannot convert
from element type capture#3-of ?
to Map.Entry<? extends K,? extends V>
ho alterato il tipo della dichiarazione di entrySet
a Set<Map.Entry<? extends K, ? extends V>>
. Questa volta, l'errore viene indicato nella parte di inizializzazione della dichiarazione, dicendo:
public void putAll(final Map<? extends K, ? extends V> mapToCopy) {
Set<Map.Entry<? extends K, ? extends V>> entrySet = mapToCopy.entrySet();
^^^^^^^^^^^^^^^^^^^^
for (Map.Entry<? extends K, ? extends V> entry : entrySet) {
}
}
Type mismatch: cannot convert
from Set<Map.Entry<capture#1-of ? extends K,capture#2-of ? extends V>>
to Set<Map.Entry<? extends K,? extends V>>
Dal momento che il codice originale si compila, io sono un po 'perplesso. Forse qualcuno può aiutarmi e dare una spiegazione? Grazie in anticipo!
Si noti che 'Set estende Map.Entry estende K,? estende V >> entrySet = mapToCopy.entrySet(); 'funzionerà. [JLS § 14.4.2] (http://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.14.2) parla della traduzione di 'Iterable' nell'elemento avanzato dichiarazione 'for'. Vedi anche [questa risposta] (http://stackoverflow.com/a/16753901/5065475) –
@AndyBrown: puoi approfondire "Nota che [...] funzionerà", per favore. Cosa devo modificare per farlo funzionare? – Marcus
In java8, provare anche 'map.forEach ((chiave, valore) -> {...})'. chiave/valore vengono dedotti a tipi appropriati, come alcuni sottotipi sconosciuti di K/V. L'API è anche abbastanza flessibile se dettiamo i tipi - 'map.forEach ((tasto K, valore V) -> {...})' – ZhongYu