对象与可选,哪个更可取? [英] java.util.Objects vs Optional which is preferable?

查看:50
本文介绍了对象与可选,哪个更可取?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用许多新方法扩展了java.util.Objects

Objects#requireNonNullElse

分别

Java-9中的Objects#requireNonNullElseGet()

如果第一个参数为非空,则两者都将返回第一个参数,否则将返回第二个非空参数或Supplier.get()的非空值

jshell> String nullStr = null;
nullStr ==> null

jshell> Objects.requireNonNullElse(nullStr,"lorem ipsum");
$13 ==> "lorem ipsum"

jshell> Objects.requireNonNullElseGet(nullStr,() -> "lorem ipsum");
$14 ==> "lorem ipsum"

但新功能与OptionalOptional#orElseOptional#orElseGet中已有的功能重叠

jshell> Optional.ofNullable(nullStr).orElse("lorem ipsum");
$17 ==> "lorem ipsum"

jshell> Optional.ofNullable(nullStr).orElseGet(() -> "lorem ipsum");
$18 ==> "lorem ipsum"
Objects中的新方法与对应的Optional方法之间的唯一区别是供应商的第二个参数或值必须为非空,否则Objects抛出NPE

jshell> Objects.requireNonNullElseGet(nullStr,() -> null);
|  java.lang.NullPointerException thrown: supplier.get()
|        at Objects.requireNonNull (Objects.java:246)
|        at Objects.requireNonNullElseGet (Objects.java:321)
|        at (#15:1)

jshell> Objects.requireNonNullElse(nullStr,null);
|  java.lang.NullPointerException thrown: defaultObj
|        at Objects.requireNonNull (Objects.java:246)
|        at Objects.requireNonNullElse (Objects.java:301)
|        at (#16:1)

Optional

jshell> Optional.ofNullable(nullStr).orElse(null);
$19 ==> null

jshell> Optional.ofNullable(nullStr).orElseGet(() -> null);
$20 ==> null
  • 为什么JDK开发人员没有更新可选中的现有方法 类?
  • 他们为什么不引入一个新的方法(它将抛出 如果第二个参数为空,则为NPE)到可选类?
  • 现在我们应该使用什么可选的或对象?
  • 新方法是否使对象比可选方法更可取,因为它们 将立即抛出NPE,而不是稍后抛出代码中的某个地方 就像可选?

如果我有遗留代码,则如下所示:

String str = null; 
String result = str == null ? "other string" : str;

这只是一个方法内部的简单检查。我想使用最新的语言功能对其进行重新分解。现在,请注意Optional.orElseObjects.requireNonNullOrElse哪个更可取?

result = Optional.ofNullable(str).orElse("other string");

result = Objects.requireNonNullOrElse(str,"other string);

推荐答案

您的问题"哪个更好?"是开发人员最喜欢的😜,因为Objects::requireNonNullElseOptional涵盖了不同的用例。

两个替代方案

在回答您的问题之前,我想先介绍一下这两个备选方案的背景信息。

Objects::requireNonNullElse

Objects::requireNonNull确保调用的结果不为空(因此而得名)。它通常用于简洁地验证构造函数或方法参数,并允许读者一目了然地验证返回值所赋给的变量不能为空。

因此,Objects::requireNonNullElse突然允许null不仅是奇怪的,而且也是无用的,因为:

// if requireNonNullGet would allow null as second argument,
// the following is true for all x (including null)
Objects.requireNonNullElse(x, null) == x
您可能会认为requireNonNullElseGet不同,因为它可能会调用一个函数,而该函数可能会根据某种状态返回null,也可能不会返回。这是真的,我认为这是经过考虑的,但如果这三种情况之一实际上可能允许调用的最终结果为null,那么requireNonNull...API将非常奇怪,即使名称显示Required Non Null

Optional

Optionalwas designed作为返回参数,用于返回null很可能导致NPE的情况(例如,对于Stream的终端操作,它最初是在那里使用的)。尽管一些开发人员更喜欢在更多的情况下使用它(请比较Stephen Colebourne's pragmatic approachmy strict approach),但没有人真正建议像您的演示中那样使用它:

Optional.ofNullable(nullStr).orElse(null);
Optional.ofNullable(nullStr).orElseGet(() -> null);

Optional是在类型系统中表示可能缺少某些内容的一种方式-它不是if-null-检查的替代方法。从这个意义上讲,orElseorElseGetOptional返回可空类型世界的后门,有时null只是您在没有什么东西的情况下想要使用的,所以它们接受null作为参数(或供应商的结果)是有意义的。

您的问题

现在我们有了回答您的问题所需的内容:

为什么JDK开发人员没有更新可选类中的现有方法?

从概念上讲,这将与Optional的用途背道而驰。但是,正如其他人所提到的,这将是一个向后不兼容的更改,因为对orElse(null)的调用会突然引发异常。

为什么他们没有向可选类引入新方法(如果第二个参数为空则抛出NPE)?

只有在现有代码有望得到显著改进的情况下,才会扩展API。我在这里看不到这一点。在许多情况下,orElse获取调用者专门创建的参数,作为空选项的替代选项-很少需要进行额外的检查来验证它不是null。如果真的需要,请拨打orElse(requireNonNull(x))

现在我们应该使用什么可选的或对象?

如果您有一个变量(可以是局部变量、参数或字段),并且希望确保它不为空,请使用Objects。如果您想要返回一些可能为空的内容,请考虑将其包装在Optional中。对于创建Optional(而不是从调用中获取一个)并在同一链的末尾将其解包的代码要持怀疑态度。

新方法是否使对象比可选更可取,因为它们会立即抛出NPE,而不是稍后在代码中的某个位置抛出(如可选)?

我相信现在已经很清楚了,它们涵盖了不同的用例。但让我来说明"而不是稍后在代码中的某个地方使用Optional":无论您做什么,都要确保在代码中检查所需的nullablity属性(可以是null,也可以不是)。不要返回您认为不可能null的东西,但事实证明这是因为您没有检查。如果发生这种情况,则不是Optional的错误。

如果我有遗留代码,则如下所示:

String str = null; 
String result = str == null ? "other string" : str;

确定Objects.requireNonNullOrElse(str,"other string");并考虑使用静态导入以使其更具可读性。

这篇关于对象与可选,哪个更可取?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆