Я наткнулся на некоторые, по крайней мере для меня, странное поведение в Eclipse 4.4 и Java 8 build 45 при выполнении рефакторинга экспрессии. Следующий пример показывает оригинальную и без ошибок коды перед применением экстракта рефакторинга:Несоответствие типов после извлечения выражения с общим типом возвращаемого значения
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()) {
}
}
}
результата рефакторинга Eclipse, выглядит, как это и приводит к сообщению об ошибке ниже, который ссылается на доступ для чтения из entrySet
в объявление цикла:
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>
я изменил тип объявления entrySet
к Set<Map.Entry<? extends K, ? extends V>>
. На этот раз, ошибка отображается в инициализаторе декларации, говоря:
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>>
Поскольку исходный код компилируется, я немного озадачен. Может быть, кто-то может мне помочь и дать объяснение? Заранее спасибо!
Обратите внимание, что 'Set extends Map.Entry расширяет K,? extends V >> entrySet = mapToCopy.entrySet(); 'будет работать. [JLS § 14.4.2] (http://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.14.2) говорит о переводе 'Iterable' в расширенном 'for'. Также см. [Этот ответ] (http://stackoverflow.com/a/16753901/5065475) –
@AndyBrown: Можете ли вы подробнее остановиться на «Обратите внимание, что [...] будет работать», пожалуйста. Что мне нужно изменить, чтобы заставить его работать? – Marcus
В java8 также попробуйте 'map.forEach ((ключ, значение) -> {...})'. ключ/значение выводятся на соответствующие типы, как неизвестный подтип K/V. API также достаточно гибкий, если мы диктуем типы - 'map.forEach ((К-ключ, значение V) -> {...})' – ZhongYu