2

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

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

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

4

2 回答 2

2

JDT 的 null 分析无法了解 JRE 和其他库中每个方法的语义。因此,没有任何结论可以通过看到调用来得出ifPresent。这可以通过添加外部注释来解决,Optional以便分析将方法ofNullable视为

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

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

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

于 2015-06-18T21:37:42.143 回答
1

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

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

run 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"));
}
于 2015-06-18T11:20:42.967 回答