Optional.ofNullable() 和 `Optional.of() 有什么区别

What is the difference between Optional.ofNullable() and `Optional.of()

首先我知道这两种方式的区别

所以,如果我在上面加上 orElseThrow(() -> new NullPointerException("null data")),结果会一样吗?

我想抛出带有显式内容的错误。

所以我得到 Optional.ofNullable(data).orElseThrow(() -> new NullPointerException("null data")))

把它当作这种毫无意义的行为吗?

Optional.of(data).orElseThrow(() -> new NullPointerException("null data")))

我认为这也是可能的,但我只是使用 ofNullable() 让代码看起来一致。

总而言之, 最后,如果您添加 orElseThrow(nullPoint) ofofNullable 是相同的结果吗?

然后宁愿 of.orElseThrow 更好吗?

to sum it up, In the end, if you add orElseThrow(nullPoint) Are of or ofNullable the same result?

没有。要了解这一点,只需查看类型即可。

public static <T> Optional<T> of(T value);

public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier)
                               throws X extends Throwable;

Optional.of returns 一个 Optional<T>,其中 orElseThrow 会给你留下一个 T。所以Optional.ofNullable(x).orElseThrow(...)真的只是一个非常迂回的地方

if (x == null) {
  throw new NullPointerException(...);
}

您实际上并没有Optional任何事情,只是制作一个然后以非常冗长的方式丢弃它。因此,如果这是您的意图,只需进行明确的 null 检查;根本不需要 Optional.

这就提出了我们为什么要使用 ofofNullable 的问题。随着Optional的引入,Java中“这个值可能不存在”的概念现在有两种表示方式:nullOptional.empty()。互联网上的人们会争论到底哪个更好,什么时候应该使用哪个(我对此有强烈的看法,我不会在这里分享,因为这不是你问的),但重点是有两种不同的方法。

对于这个 post 的其余部分,我会从 Kotlin 那里借用一些符号并写 T? 来表示“一个 T 值可能是 null”。它不是有效的 Java 表示法,但它明白了要点。因此,如果我们想在 Java 中表示“A T which may or may not exist”,我们可以使用 Optional<T>T?.

如果我们想从 T?Optional<T>,这就是 Optional.ofNullable 的目的。它说“如果东西是null,给我Optional.empty();否则给我Optional中的东西”。反过来,我们可以使用 Optional.orElse(null),它表示“如果我有一个 T,给我,否则给我看 null”。所以现在我们有办法在这两种方法之间进行转换。那么 Optional.of 有什么用?

您应该将 Optional.of 视为某种断言。如果 Java 具有像 Kotlin 这样的可空类型,那么区别将类似于

public static <T> Optional<T> of(T value);
public static <T> Optional<T> ofNullable(T? value);

也就是说,ofNullable 期望它的值可能是 nullof 已经假设它不是。 Optional.of 应该被认为是一个断言,你给它的值不为空。如果该断言失败,我们会立即抛出 NullPointerException 而不是让错误传播到程序的其他部分。如果您正在调用 Optional.of 并从 NullPointerException 中恢复,它会抛出 [1],那么您正在做一些 非常错误的事情.该函数是我们开始处理 non-null 数据的一个断言,如果该断言失败,那么您的程序应该立即失败并具有良好的堆栈跟踪。

听起来,根据您的用例,您的值可能是 null。在那种情况下,Optional.ofNullable 是有道理的;它已准备好处理用例。如果你想抛出一个自定义异常,你应该事先做一个空检查(因为你是处理null的人,而不是Optional)然后打电话 Optional.of。或者,当然,如果您打算使用 orElseThrow 提取它,您可以只进行 old-fashioned null 检查而根本不使用 Optional。当然,一行中的管道 Optional.ofNullable(value).orElseThrow(...) 会产生代码味道。


[1] 注意我说的是“恢复”,而不是“捕捉”。记录所有错误的好 top-level catch (Exception exc) 是完全可以接受的,并且在大型应用程序中通常是个好主意。但是如果你正在做 catch (NullPointerException exc) { return 0; } 或类似的事情,那么你需要重新考虑你应该使用哪种 Optional 方法。

First of all, I know the difference between the two methods.

Optional.of : Used to ensure that there is no null, if null is entered, nullPointExcepction

Optional.ofNullable : may or may not be null. Used to respond flexibly.

有一个明显的误会。

Optional.of()的目的不是”保证没有null。它并不意味着被用作传递给它的值是 non-null 的断言。对于这样的验证,你可以使用 Objects.requireNonNull(),它会抛出一个 NPE,或者 return 你会抛出一个 non-null值.

为了在同一页面上,您必须记住的第一件重要的事情是 optionals 在 JDK 中仅引入 一个特定的目的 - 作为return类型。当 optional 用作 parameter-type 或 field-type 或当可选对象存储在集合中时,任何其他情况不被视为好的做法。同样,创建 optional 只是为了在其上链接方法或隐藏 null-check 被认为是 反模式.

来自 @StuartMarks 的回答,JDK:

的开发者

The primary use of Optional is as follows:

Optional is intended to provide a limited mechanism for library method return types where there is a clear need to represent "no result," and where using null for that is overwhelmingly likely to cause errors.

A typical code smell is, instead of the code using method chaining to handle an Optional returned from some method, it creates an Optional from something that's nullable, in order to chain methods and avoid conditionals.

我还建议你看看 这个问题的答案,也是 Stuart Marks

综上所述,组合 Optional.of().orElseThrow() 既错误又毫无意义:

  • 如果提供的数据是 null 方法 of() 将引发 NPE 并且 orElseThrow() 将不会被执行(即它的异常将永远不会被解雇).
  • 您正在滥用 optional 创建一个可选对象,而不是为了 return 一个 可空变量 包裹它,但要隐藏 null-check( 看看上面的引用 )。这掩盖了你的代码的目的。如果给定值不能为 nullrequireNonNullElse() 以提供默认值,则可以使用 Objects.requireNonNull() 来抛出异常。

出于同样的原因,您不应该首先使用 Optional.ofNullable().orElseThrow()

可选的就像一个盒子

你可能会认为 optionalparcel。当你需要发送东西时,你去post办公室(returning从方法),必须发送的东西被放入 盒子 中。当某人(来电者)收到包裹时,它会立即被解包。这就是名为 Optional.

的盒子的整个生命周期

当根据您的应用程序的逻辑,需要从方法中 return 编辑的对象不应该 null - 使用 Optional.of()。它要么成功发送包裹,要么通过提出 NullPointerException.

来强调存在问题

如果给定的对象本质上是 nullable,即 null 不是异常情况,则使用 Optional.ofNullable(),它将触发包含对象的框或空框。

调用者即调用方法return可选的方法)是必须使用 optional 提供的各种工具解压 box,例如 orElseThrow()orElseGet()ifPresent()、等等