Ошибка "несоответствие нулевых ограничений" при реализации Map.entrySet (Java8, Eclipse)
Я получаю ошибку...
The return type is incompatible with 'Set<Map.Entry<K,T>>' returned from Map<K,T>.entrySet() (mismatching null constraints)
... при реализации Map
и переопределение Map.entrySet
как это:
package org.abego.util;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
...
public abstract class MyMap<K, T> implements Map<K, T> {
private Map<K, T> map = new LinkedHashMap<>();
@Override
public Set<java.util.Map.Entry<K, T>> entrySet() {
return map.entrySet();
}
...
}
Посылка org.abego.util
определяет недействительность по умолчанию, чтобы быть @NonNull
:
@org.eclipse.jdt.annotation.NonNullByDefault
package org.abego.util;
Единственный способ избавиться от ошибки - "удалить аннотацию по умолчанию" для entrySet
используя @NonNullByDefault({})
аннотация:
package org.abego.util;
...
import org.eclipse.jdt.annotation.NonNullByDefault;
public abstract class MyMap<K, T> implements Map<K, T> {
...
@Override
@NonNullByDefault({})
public Set<java.util.Map.Entry<K, T>> entrySet() {
return map.entrySet();
}
...
}
Хотя это работает, мне интересно, если это правильный способ исправить ошибку.
(Я использую Eclipse 4.5 (Mars) и jdk1.8.0_60.)
1 ответ
Вы пытаетесь переопределить этот метод:
Set<Map.Entry<K, V>> entrySet();
с методом, чья эффективная подпись
@NonNull Set<@NonNull Map.Entry<K, V>> entrySet();
Это несовместимое переопределение, которое можно продемонстрировать с помощью этого вызывающего абонента:
Set<Map.Entry<Foo,Bar>> entries = someMap.entrySet();
entries.add(null);
Если someMap
имеет тип MyMap
тогда тип элемента entries
является @NonNull
, но контракт java.util.Map.entrySet()
обещает Set
где null
элементы допускаются (множество не указало недействительность своих элементов). Смешивание обоих контрактов (с @NonNull
и не указано) на том же объекте entries
сломает клиентов, которые принимают ненулевые элементы.
Глядя на Javadoc entrySet()
однако следует с уверенностью предположить, что Map.entrySet()
всегда будет возвращать Set
с ненулевыми элементами. Следовательно, корень проблемы заключается в том, что java.util.Map.entrySet()
не имеет нулевых аннотаций
Начиная с "Затмения Марса", это можно преодолеть с помощью внешних нулевых аннотаций. Вы можете сказать компилятору, что тип возвращаемого значения Map.entrySet()
на самом деле @NonNull Set<@NonNull Map.Entry<K,V>>
либо применяя команду Annotate в IDE, либо помещая следующий фрагмент в файл java/util/Map.eea
внутри каталога, который был настроен как место для внешних аннотаций для JRE:
class java/util/Map
entrySet
()Ljava/util/Set<Ljava/util/Map$Entry<TK;TV;>;>;
()L1java/util/Set<L1java/util/Map$Entry<TK;TV;>;>;
С такими внешними аннотациями ваша программа будет принята нулевым анализом JDT.