我是Java 8新手并尝试Null类型注释和Optional。
对于我下面的例子,我使用了String而不是我的类,并且调用toUpperCase只是为了调用一些东西,在我的情况下我实际上调用了一个传递参数的函数(所以不要认为我可以使用:: operator和/或地图)。
在Eclipse中,我有Java - 编译器 - 错误/警告 - 启用了空分析错误。
我的测试代码如下:
public void test1(@Nullable String s) {
// the 2nd s2 has a Potential null pointer access error.
// I was hoping ifPresent would imply NonNull
Optional.ofNullable(s).ifPresent(s2 -> s2.toUpperCase());
}
@Nullable
public String getSomeString() {
return null;
}
public void test2() {
String s = getSomeString();
// This is fine, unlike the first example, I would have assumed that
// it would know s was still nullable and behave the same way.
Optional.ofNullable(s).ifPresent(s2 -> s2.toUpperCase());
}
使用Eclipse类型的null注释和Optional.ifPresent似乎不能很好地结合在一起。
我是否在浪费时间尝试这样的工作?我是否应该恢复将getter分配给temp var然后检查是否为null,如果不调用我的函数?
答案 0 :(得分:2)
JDT的null分析无法了解JRE和其他库中每个方法的语义。因此,看到对ifPresent
的调用没有得出任何结论。这可以通过向Optional
添加外部注释来解决,以便分析将方法ofNullable
视为
<T> Optional<@NonNull T> ofNullable(@Nullable T value)
从2015年6月24日发布的Eclipse Mars开始支持外部注释。请参阅Help: Using external null annotations。
问题中两个变体之间的差异是由于null分析如何与Java 8类型推断集成:变体(1)s
具有类型@Nullable String
。在类型推断期间使用此类型时,可以得出结论:ifPresent
的参数也可以为空。在变体(2)中,s
具有类型String
(尽管流分析可以看到在从getSomeString
初始化之后可能为空)。未注释的类型String
不足以帮助类型推断得到与变体(1)相同的结论(虽然这可能在未来的JDT版本中得到改进)。
答案 1 :(得分:1)
第一个:@Nullable
接缝不属于公共 Java 8 SDK 。看看您导入的软件包:com.sun.istack.internal.Nullable
。
第二:我已经运行了两种方法:test1(null)
和test2()
,并没有发生任何异常情况。一切都很好(正如预期的那样)。那你看到了什么?
运行test1(null)
=&gt;没有执行lambda表达式。
运行test2()=&gt;没有执行lambda表达式。
我通过以下方式更改了代码以进行测试:
public void test1(@Nullable String s) {
Optional.ofNullable(s).ifPresent(s2 -> System.out.println("executed"));
}
public void test2() {
String s = getSomeString();
Optional.ofNullable(s).ifPresent(s2 -> System.out.println("executed"));
}