为什么要使用Optional.of而不是Optional.ofNullable?


232

使用Java 8 Optional类时,有两种方法可以将值包装在可选值中。

String foobar = <value or null>;
Optional.of(foobar);         // May throw NullPointerException
Optional.ofNullable(foobar); // Safe from NullPointerException

我知道这Optional.ofNullable是唯一安全的使用方法Optional,但是为什么根本不Optional.of存在呢?为什么不总是使用Optional.ofNullable 并且始终保持安全呢?


1
请告诉我必须导入哪个软件包才能使用此软件包?
LoveToCode

4
@LoveToCode java.util.Optional-它的面世,如果你正在使用JDK 8或更高版本
whirlwin

11
我很想知道他们是否可以ofNullable()命名of()of()命名ofNotNull()
Robert Niestroj


当您问“为什么Optional.of根本存在?为什么不只使用Optional.ofNullable并始终保持安全呢?” 假设如果用户所需的数据不存在,那么我们必须抛出异常。因此,这完全取决于您的用例。baeldung.com/java-optional-throw-exception
卡伦·阿拉

Answers:


306

您的问题基于以下假设:可能抛出NullPointerException的代码比可能不会抛出的代码更糟糕。这个假设是错误的。如果您希望foobar由于程序逻辑而永远不会为null,那么最好使用它,Optional.of(foobar)因为您会看到,NullPointerException这表明您的程序存在错误。如果您使用Optional.ofNullable(foobar)并且foobar碰巧是null由于该错误所致,则您的程序将在无提示的情况下继续正常运行,这可能是更大的灾难。这样,错误可能会在更晚的时候发生,并且在那一点上更难理解。


129
如果由于程序逻辑而期望foobar永远不会为null,那么使用Optional.of(foobar)会更好。这似乎有点奇怪-当我们知道null在任何情况下都不会使用该值时,为什么不使用该值本身,而不是将其包装在Optional?中?
康斯坦丁·约夫科夫

54
@kocko,您可能必须根据Optional要实现的接口的要求从方法中返回(可能其他实现者可能会返回一个空的可选)。或者您想创建一个可选项的集合/流,其中某些保证为非null,而另一些则不是。或者,您具有条件逻辑,该条件逻辑会在多个分支中创建一个可选项,而在单个分支中,请确保它不是空值。
塔吉尔·瓦列夫2015年

28
因为Optional表示可以存在或不存在。不存在!= null。null在这种情况下,意味着“我希望foobar存在,但是由于错误,它为null”。Optional.isPresent() == false表示不存在foobar,即这是预期的合法行为。
布曼2015年

43
@kocko:简单的例子:return list.isEmpty()? Optional.empty(): Optional.of(list.get(0));list预计不会包含null...价值观
霍尔格

5
@Harish如果您要问我,我建议您不要在所有地方都使用Optionals。那是一个单独的问题。您可以在这里查看一些意见。
塔吉尔·瓦列夫

12

此外,如果您知道如果object为null,则代码不起作用,则可以使用以下方法引发异常: Optional.orElseThrow

String nullName = null;
String name = Optional.ofNullable(nullName).orElseThrow(NullPointerException::new);

1
但是,为此,您可以使用更短的时间String name = Objects.requireNonNull(nullName);
Holger

1
@Holger好点,但是.orElse()方法允许自定义异常,这些异常可能有助于您更好地处理控制流或信息记录。
Nikos Stais

1
好了,您可以提供有关异常的消息以提供其他信息。进行任何其他自定义尝试(例如使用不同于NullPointerException问题明显地是null应该不应该的参考的异常)将是朝错误方向迈出的一步。
Holger

此外,您还可以使用可选的抛出更具体的(如自定义)异常,而不是NPE,NPE是太普通了,你可以扔掉像new NullNameException("meaningful msg")
戴维

1

这取决于方案。

假设您具有一些业务功能,并且需要进一步处理具有该价值的商品,但是null在处理时具有价值会对其产生影响。

然后,在这种情况下,您可以使用Optional<?>

String nullName = null;

String name = Optional.ofNullable(nullName)
                      .map(<doSomething>)
                      .orElse("Default value in case of null");

0

无论如何,可选项应主要用于服务结果。在服务中,您知道手头有什么,如果有结果,则返回Optional.of(someValue),否则,则返回Optional.empty()。在这种情况下,某些值永远不应为null,而且您仍返回Optional。


1
感谢您对Sumesh的编辑,但是您最后编辑为“ some Value”的最后一行中的“ someValue”引用了上面“ Optional.of(someValue)”中的变量,我认为应该保持someValue。
espendennis
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.