为啥使用 Optional.of 而不是 Optional.ofNullable?

Posted

技术标签:

【中文标题】为啥使用 Optional.of 而不是 Optional.ofNullable?【英文标题】:Why use Optional.of over Optional.ofNullable?为什么使用 Optional.of 而不是 Optional.ofNullable? 【发布时间】:2015-10-20 04:48:01 【问题描述】:

使用 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 并始终保持安全?

【问题讨论】:

请告诉我必须导入哪个包才能使用它? @LoveToCode java.util.Optional - 如果您使用的是 JDK 8 或更高版本,则可用 如果他们将ofNullable() 命名为of()of() 命名为ofNotNull(),我会很高兴 请参考baeldung.com/java-optional 当您问“为什么 Optional.of 存在?为什么不直接使用 Optional.ofNullable 并始终保持安全?”假设如果用户所需的数据不存在,那么我们必须抛出异常。因此,这完全取决于您的用例。 baeldung.com/java-optional-throw-exception 【参考方案1】:

您的问题是基于这样的假设,即可能抛出NullPointerException 的代码比可能不会抛出的代码更糟糕。这个假设是错误的。如果您希望您的foobar 由于程序逻辑而永远不会为空,那么使用Optional.of(foobar) 会更好,因为您会看到NullPointerException 这将表明您的程序有错误。如果你使用Optional.ofNullable(foobar)foobar 恰好是null 由于该错误,那么你的程序将默默地继续不正确地工作,这可能是一个更大的灾难。这样一来,错误可能会在很久以后才发生,并且更难理解它是在什么时候出错的。

【讨论】:

"如果您希望 foobar 由于程序逻辑而永远不会为空,则最好使用Optional.of(foobar)"。这似乎有点奇怪 - 当我们知道值不会是 null 在任何情况下,那么为什么不使用值本身,而不是将其包装在 Optional 中? @kocko,您可能必须根据您正在实现的接口的要求从方法中返回Optional(可能其他实现者可能会返回一个空的可选项)。或者你想创建一个可选的集合/流,其中一些保证非空,而有些则不是。或者你有条件逻辑,它在多个分支中创建一个可选的,在单个分支中你确定它是非空的。 因为可选意味着它可以存在或不存在。缺席!= null。 null 在这种情况下意味着“我希望 foobar 存在,但由于错误它为空”。 Optional.isPresent() == false 表示 foobar 不存在,即这是预期的合法行为。 @kocko:简单示例:return list.isEmpty()? Optional.empty(): Optional.of(list.get(0)); list 预计永远不会包含 null 值... @Harish 如果你问我,我不建议在任何地方使用 Optionals。那是一个单独的问题。您可以查看一些意见here。【参考方案2】:

另外,如果你知道你的代码在 object 为 null 时不应该工作,你可以使用 Optional.orElseThrow

抛出异常
String nullName = null;

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

【讨论】:

但是为此,您可以使用更短的String name = Objects.requireNonNull(nullName); 好点 @Holger,但是 .orElse() 方法允许自定义异常,这可能有助于您更好地处理控制流或信息记录。 好吧,您可以为异常提供一条消息以提供更多信息。任何其他自定义尝试,例如使用与NullPointerException 不同的异常,当问题显然是null 的引用而它不应该时,将是朝着错误方向迈出的一步。 另外,您可以使用 Optional 来抛出更具体的(例如自定义)异常,而不是 NPE,NPE 太通用,您可以抛出类似 new NullNameException("meaningful msg") 这不正是 Optional.of(value) 的作用吗?如果值为 null,则抛出 NullPointerException?【参考方案3】:

这取决于场景。

假设您有一些业务功能,并且您需要进一步处理具有该值的东西,但在处理时具有 null 值会影响它。

那么,在这种情况下,您可以使用Optional&lt;?&gt;

String nullName = null;

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

【讨论】:

【参考方案4】:

无论如何,Optional 应该主要用于服务的结果。在服务中,您知道您手头有什么,如果有结果则返回 Optional.of(someValue) ,如果没有则返回 Optional.empty()。在这种情况下, someValue 永远不应该为 null 并且仍然返回一个 Optional。

【讨论】:

感谢 Sumesh 的编辑,但您编辑为“某个值”的最后一行中的“someValue”引用了上面“Optional.of(someValue)”中的变量,应该保留一些价值,我想。

以上是关于为啥使用 Optional.of 而不是 Optional.ofNullable?的主要内容,如果未能解决你的问题,请参考以下文章

Java8新特性 - Optional容器类

Optional类型

如果我们将Optional.of方法设为私有,并且只允许Java中的Optional.ofNullable,该怎么办?除了向后兼容性会有什么问题吗?

Java8新特性--Optional

java8--- Optional的使用

Optional 容器类