2015-09-12 1 views
1

я получаю ошибку ...Получение 'несовпадающих непустые значения' ошибка при выполнении 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 определяет nullness по умолчанию быть @NonNull:

@org.eclipse.jdt.annotation.NonNullByDefault 
package org.abego.util; 

Единственный способ я нашел, чтобы избавиться от ошибок было «удалить nullness по умолчанию аннотацию к» для 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 (Марс) и jdk1.8.0_60.)

ответ

0

Вы пытаетесь переопределить этот метод:

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 элементы переносимой (набор не указан nullness его элементов). Смешивание обоих контрактов (с @NonNull и неуказанным) на том же объекте entries приведет к разрыву клиентов, которые принимают непустые элементы.

Глядя на Javadoc из entrySet(), это должно быть, однако можно предположить, что Map.entrySet() будет всегда возвращает Set с непустыми элементами. Следовательно, корень проблемы заключается в том, что java.util.Map.entrySet() не имеет нулевых аннотаций.

С Eclipse Mars это можно преодолеть путем external null annotations. Вы можете сказать компилятору, что тип возвращаемого Map.entrySet() фактически является @NonNull Set<@NonNull Map.Entry<K,V>>, либо путем применения Annotate command в IDE, или поместив следующий фрагмент кода в файл java/util/Map.eea внутри каталога, который был configured as the location for external annotations для 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.

+0

Спасибо, что решила проблему. Теперь я использую функцию внешнего аннотации для других проблем, с которыми я столкнулся. В основном это означает добавление аннотаций методам JRE к «моим» внешним файлам аннотаций.Поскольку я, вероятно, не единственный, сталкивающийся с такими проблемами, мне интересно, существует ли уже какое-то место (например, репозиторий Git или так), в котором хранятся внешние файлы аннотаций, например. Java 1.8 JRE. –

+0

Согласно https://wiki.eclipse.org/JDT_Core/Null_Analysis/External_Annotations#Collecting_annotations, что вы запрашиваете, действительно на нашей дорожной карте. Первое, что стоит на повестке дня: зная, что другие выпустили аннотации для JRE, Eclipse предложит мастер для импорта этих аннотаций из банки в наш текстовый формат. Еще позже ... –