Java 8 Optional.ifPresent是我的代码错了还是eclipse?

时间:2015-06-18 10:32:36

标签: eclipse java-8 nullable optional external-annotations

我是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,如果不调用我的函数?

2 个答案:

答案 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"));
}