Java 8 Optional.ifPresent是我的代码错误还是日食



我是Java 8的新手,正在尝试Null类型注释和可选。

对于下面的示例,我使用了 String 而不是我的类,并且调用 toUpper Case 只是为了调用某些东西,在我的情况下,我实际上调用了一个传入参数的函数(所以不要认为我可以使用 :: 运算符和/或地图)。

在 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 类型的空注释和 Optional.ifPresent 不能很好地结合在一起。

我是否在浪费时间试图让这样的事情发挥作用?我是否应该恢复到将 getter 分配给临时变量,然后检查是否为 null,如果不调用我的函数?

JDT 的空分析无法了解 JRE 和其他库中每个方法的语义。因此,通过看到ifPresent的呼吁不会得出任何结论。这可以通过在Optional中添加外部注释来补救,以便分析将方法ofNullable视为

<T> Optional<@NonNull T> ofNullable(@Nullable T value)

从 2015 年 6 月 24 日发布的 Eclipse Mars(Eclipse Mars)开始,支持外部注释。请参阅帮助:使用外部空注释。

问题中两个变体之间的差异是由于空分析如何与 Java 8 类型推理集成:在变体 (1) 中,s 具有类型 @Nullable String 。在类型推断期间使用此类型时,可以得出结论,ifPresent参数也是可为空的。在变体 (2) 中,s 具有类型 String(尽管流分析可以看到在从 getSomeString 初始化后可能为 null)。未注释的类型String不足以帮助类型推断得出与变体 (1) 相同的结论(尽管这可能会在 JDT 的未来版本中得到改进)。

首先:@Nullable接缝不是公共Java 8 SDK的一部分。看看您导入的包:com.sun.istack.internal.Nullable

第二:我已经运行了你的两种方法:test1(null)test2(),没有发生任何异常。一切都很好(正如预期的那样)。那么你观察到了什么?

运行 test1(null) => 不执行 lambda 表达式。

运行 test2() => 不执行 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"));
}

相关内容

最新更新