实现 Map.entrySet 时出现 'mismatching null constraints' 错误(Java8,Eclipse)
Getting 'mismatching null constraints' error when implementing 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;
我发现消除错误的唯一方法是 'remove the default nullness annotation' for 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。)
您正试图覆盖此方法:
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
个元素(集合未指定其元素为空)。在同一个对象 entries
上混合两个合同(@NonNull
和未指定)将破坏假定非空元素的客户端。
查看 entrySet()
的 Javadoc,但是可以安全地假设 Map.entrySet()
将 always return a Set
与非空元素。因此,问题的根源在于 java.util.Map.entrySet()
没有空注释。
自 Eclipse Mars 以来,这可以通过 JRE 的 external null annotations. You can tell the compiler that the return type of Map.entrySet()
is in fact @NonNull Set<@NonNull Map.Entry<K,V>>
, either by applying the Annotate command in the IDE, or by putting the following snippet into a file java/util/Map.eea
inside a directory that has been configured as the location for external annotations 来克服:
class java/util/Map
entrySet
()Ljava/util/Set<Ljava/util/Map$Entry<TK;TV;>;>;
()L1java/util/Set<L1java/util/Map$Entry<TK;TV;>;>;
有了这样的外部注释,您的程序将被 JDT 的空分析接受。
我收到错误...
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;
我发现消除错误的唯一方法是 'remove the default nullness annotation' for 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。)
您正试图覆盖此方法:
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
个元素(集合未指定其元素为空)。在同一个对象 entries
上混合两个合同(@NonNull
和未指定)将破坏假定非空元素的客户端。
查看 entrySet()
的 Javadoc,但是可以安全地假设 Map.entrySet()
将 always return a Set
与非空元素。因此,问题的根源在于 java.util.Map.entrySet()
没有空注释。
自 Eclipse Mars 以来,这可以通过 JRE 的 external null annotations. You can tell the compiler that the return type of Map.entrySet()
is in fact @NonNull Set<@NonNull Map.Entry<K,V>>
, either by applying the Annotate command in the IDE, or by putting the following snippet into a file java/util/Map.eea
inside a directory that has been configured as the location for external annotations 来克服:
class java/util/Map
entrySet
()Ljava/util/Set<Ljava/util/Map$Entry<TK;TV;>;>;
()L1java/util/Set<L1java/util/Map$Entry<TK;TV;>;>;
有了这样的外部注释,您的程序将被 JDT 的空分析接受。