如何摆脱此示例代码中的警告。
我将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());
}
}
}
警告是:
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>>'
我尝试了几种@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();
但我完全迷失了原因。在我看来,我欺骗了验证器失去了轨道或某些东西,而且代码真的开始变得难看。
全新代码:
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());
}
}
}
更新2 Shorty粘贴了错误的代码。
答案 0 :(得分:1)
Set<@NonNull X>
和Set<@Nullable X>
等问题类型的核心是不兼容的:两者都不可分配给另一个。
即使:如果您有Set<@NonNull X>
个客户希望提取非空元素,并且如果该集合实际为Set<@Nullable X>
则会中断。相反,如果您有Set<@Nullable X>
个客户希望能够插入 null
到集合中,并且如果该集合实际上是Set<@NonNull X>
则会中断。
只要您需要处理我们缺乏足够知识的“遗留”类型Set<X>
,这些注意事项就相关:它可能是Set<@NonNull X>
或Set<@Nullable X>
。类型检查必须考虑两种可能性(客户可能依赖于任一假设,因为例如,javadoc可以这样说)。
通常,在Java中,读取与写入问题通过使用有界通配符来解决:Set<? extends X>
确保读取访问将始终产生“至少”X(或更好)。 Set<? super X>
确保插入新元素的要求是“最多”X,即,任何X或更好的将被接受到集合中(无论实际列表的实际要求是什么)。
要将上述内容应用于null注释,只需说Set<? extends @Nullable X>
接受旧版集并支持从集合中读取(值至少为@Nullable X
,可能会更好,例如{{1} })。
如果需要插入旧版集,请将其分配给@NonNull X
类型的变量。这告诉类型检查器,Set<? super @NonNull X>
总是足以插入。
这就是@NonNull X
接受Set<? extends @Nullable Entry<..>
的结果的原因,treeMap.entrySet()
实际上具有Set<Entry<@Nullable Integer, @Nullable String>>
类型。这里的内部类型参数完全由treeMap
的声明注释,由于Entry
的遗留签名,只有顶级类型参数entrySet()
未指定。
最后一次提及也暗示了该示例的“真实”解决方案:使用外部注释来指示entrySet()
实际返回@NonNull Set<@NonNull Entry<K,V>>
。这样就不需要通配符魔法了。