Tor*_*rge 2 java eclipse non-nullable java-annotations
如何消除此示例代码中的警告。
我将 Eclipse Neon 与 Java 1.8 和 org.eclipse.jdt.annotation_2.1.0 结合使用
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
@NonNullByDefault
public class NullAnnotationTest4 {
public static void main(String[] args) {
final TreeMap<@Nullable Integer, @Nullable String> treeMap = new TreeMap<>();
treeMap.put(3, "Test1");
treeMap.put(null, null);
//This produces the warning
final Set<@Nullable Entry<@Nullable Integer, @Nullable String>> set = treeMap.entrySet();
for (final Iterator<@Nullable Entry<@Nullable Integer, @Nullable String>> it = set.iterator(); it.hasNext(); ) {
final Entry<@Nullable Integer, @Nullable String> entry = it.next();
if (entry != null && entry.getKey() == null && entry.getValue() != null)
System.out.println(entry.getKey()+" is mapped to "+entry.getValue());
}
}
}
Run Code Online (Sandbox Code Playgroud)
警告是:
Null type safety (type annotations):
The expression of type
'Set<Map.Entry<@Nullable Integer,@Nullable String>>'
needs unchecked conversion to conform to
'Set<Map.@Nullable Entry<@Nullable Integer,@Nullable String>>'
Run Code Online (Sandbox Code Playgroud)
我尝试了@Nullable 和@NonNullable 的几种组合。即使? extends是在类似情况下建议的:https://bugs.eclipse.org/bugs/show_bug.cgi? id=507779
但警告总是只会移动,但永远不会完全消失。
更新:
我通过使用这一行摆脱了警告:
final Set<? extends @Nullable Entry<@Nullable Integer, @Nullable String>> set = treeMap.entrySet();
Run Code Online (Sandbox Code Playgroud)
但我完全不知道为什么。在我看来,我欺骗验证器失去轨道或其他东西,代码真的开始变得丑陋。
完整的新代码:
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
@NonNullByDefault
public class NullAnnotationTest4 {
public static void main(String[] args) {
final TreeMap<@Nullable Integer, @Nullable String> treeMap = new TreeMap<>();
treeMap.put(3, "Test1");
treeMap.put(null, null);
final Set<? extends @Nullable Entry<@Nullable Integer, @Nullable String>> set = treeMap.entrySet();
for (final Iterator<? extends @Nullable Entry<@Nullable Integer, @Nullable String>> it = set.iterator(); it.hasNext(); ) {
final Entry<@Nullable Integer, @Nullable String> entry = it.next();
if (entry != null && entry.getKey() == null && entry.getValue() != null)
System.out.println(entry.getKey()+" is mapped to "+entry.getValue());
}
}
}
Run Code Online (Sandbox Code Playgroud)
更新 2 Shorty 粘贴了错误的代码。
Set<@NonNull X>像和这样的问题类型的核心Set<@Nullable X>是不兼容的:两者都不能分配给另一个。
也就是说:如果您有一个Set<@NonNull X>客户端希望提取非空元素,并且如果该集合实际上是 ,则会中断Set<@Nullable X>。相反,如果您有一个Set<@Nullable X>客户端希望能够插入 null到集合中,并且如果集合实际上是 则将会中断Set<@NonNull X>。
每当您必须处理Set<X>我们知识不足的“遗留”类型时,这些注意事项都是相关的:它可能旨在作为 aSet<@NonNull X>或 as Set<@Nullable X>。类型检查必须考虑这两种可能性(客户端可能依赖于任一假设,因为例如 javadoc 可能会这么说)。
一般来说,在 Java 中,读取与写入问题是通过使用有界通配符来解决的:Set<? extends X>确保读取访问始终会产生“至少”X(或更好)。Set<? super X>确保插入新元素的要求是“至多”X,即任何X或更好的元素都将被接受到集合中(无论实际列表的实际要求是什么)。
要将上述内容应用于空注释,只需说Set<? extends @Nullable X>接受旧集并支持从该集中读取(值至少为@Nullable X,可能更好,例如@NonNull X)。如果需要插入旧集,请将其分配给 类型的变量Set<? super @NonNull X>。这告诉类型检查器, a@NonNull X始终足以插入。
这就是为什么Set<? extends @Nullable Entry<..>接受 的结果treeMap.entrySet(),它实际上具有类型Set<Entry<@Nullable Integer, @Nullable String>>。这里内部类型参数是从 的声明中完全注释的,由于 的遗留签名,treeMap只有顶级类型参数未指定。EntryentrySet()
最后提到的还暗示了该示例的“真实”解决方案:使用外部注释来指示entrySet()实际返回@NonNull Set<@NonNull Entry<K,V>>. 这样就不需要任何通配符魔法了。