空检查与可选的 isPresent 检查

新手上路,请多包涵

有人可以解释 Optional 如何帮助我们避免 NullPointerException 吗?

 Optional<String> op = someFunc()
if(op.isPresent()) {
   op.get();
}
String possibleNull = op.get();

这段代码也容易出现 NullPointerException 吗?如果是这样,那么为什么这个代码比

String op = someFunc()
if(op != null) {
   op.get();
}
String possibleNull = op;

什么可能的好处 Optional 除了帮助我们知道一个函数是否真的有返回值这一事实之外

原文由 ffff 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 453
2 个回答

比方说你想得到一个函数返回的字符串,把它转换成大写,然后打印出来。如果你有:

 String someFunc() { ... }

你可能会想写:

 System.out.println(someFunc().toUpperCase());

当然,这抛出 NullPointerException 如果 someFunc 返回 null 。相反,假设我们有这个:

 Optional<String> someFunc() { ... }

然后

System.out.println(someFunc().toUpperCase());

不会工作,因为 Optional 没有 toUpperCase 方法。此时——希望——你会遇到一个 Optional ,这应该让你考虑 Optional 为空的情况。这有助于避免 NPE,但可能只是一点点。

现在您可能专注于如何从 Optional 中获取值,您可能会忘记空的情况。啊,有一个 get 方法:

 System.out.println(someFunc().get().toUpperCase());

这会带来与 NPE 相同的问题,除了异常是 NoSuchElementException 之外。因此,如果您盲目地在 get Optional ,这实际上与在不检查引用是否为 null 的情况下调用方法几乎是一样的。

(出于这个原因, Brian Goetz 认为 Optional.get 是 Java 8 中最大的错误。请参阅他对 Angelika Langer JAX 2015 Fragen und Antworten zu Java 8 的采访,大约 16 分钟。我不确定它是最大的,但这是一个错误。人们只是不希望 get 抛出异常。)

如果您勤于检查空引用或空可选值,那么

Optional<String> os = someFunc();
if (os.isPresent()) {
    System.out.println(os.get().toUpperCase());
}

几乎不比旧的好

String s = someFunc();
if (s != null) {
    System.out.println(s.toUpperCase());
}

Optional真正 优势在于,它是一个库类,具有相当丰富的 API,可以安全地处理空情况。通常可以通过将几个方法调用链接到首先返回 Optional 的方法来处理可能包含在 Optional 中的值。例如,我们可以将上面的示例改写如下:

 someFunc().map(String::toUpperCase)
          .ifPresent(System.out::println);

原文由 Stuart Marks 发布,翻译遵循 CC BY-SA 3.0 许可协议

Optional 有助于避免 NullPointerException 的一种情况是方法链接。

 class A {
  private B b;
}
class B {
  private C c;
}
class C {
  private D d;
}

假设我有上述类,并且我想确保类 A 的实例具有 D 的非空实例,但不会导致空指针异常。如果我直接调用 a.getB().getC().getD() != null ,那么它可能会抛出 NullPointerException - 假设 a.getB() 为空。

当然,我可以做到

try {
  a.getB().getC().getD();
  // do something
}
catch(NullPointerException e) {
  // handle exception
};

但这看起来不太好。一个优雅的解决方案是将我们的对象包装在可选中。

 Optional.ofNullable(a).map(A::getB).map(B::getC).map(C::getD).isPresent()

检查 这个 了解更多。

原文由 Aven Desta 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题