问题描述
使用许多新方法扩展了java.util.Objects类
分别
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"
但新功能与Optional
类Optional#orElse和Optional#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.orElse
和Objects.requireNonNullOrElse
哪个更可取?
result = Optional.ofNullable(str).orElse("other string");
或
result = Objects.requireNonNullOrElse(str,"other string);
推荐答案
您的问题"哪个更好?"是开发人员最喜欢的😜,因为Objects::requireNonNullElse
和Optional
涵盖了不同的用例。
两个替代方案
在回答您的问题之前,我想先介绍一下这两个备选方案的背景信息。
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
Optional
was designed作为返回参数,用于返回null
很可能导致NPE的情况(例如,对于Stream
的终端操作,它最初是在那里使用的)。尽管一些开发人员更喜欢在更多的情况下使用它(请比较Stephen Colebourne's pragmatic approach和my strict approach),但没有人真正建议像您的演示中那样使用它:
Optional.ofNullable(nullStr).orElse(null);
Optional.ofNullable(nullStr).orElseGet(() -> null);
Optional
是在类型系统中表示可能缺少某些内容的一种方式-它不是if
-null
-检查的替代方法。从这个意义上讲,orElse
或orElseGet
是Optional
返回可空类型世界的后门,有时null
只是您在没有什么东西的情况下想要使用的,所以它们接受null
作为参数(或供应商的结果)是有意义的。
您的问题
现在我们有了回答您的问题所需的内容:
从概念上讲,这将与Optional
的用途背道而驰。但是,正如其他人所提到的,这将是一个向后不兼容的更改,因为对orElse(null)
的调用会突然引发异常。
orElse
获取调用者专门创建的参数,作为空选项的替代选项-很少需要进行额外的检查来验证它不是null
。如果真的需要,请拨打orElse(requireNonNull(x))
。如果您有一个变量(可以是局部变量、参数或字段),并且希望确保它不为空,请使用Objects
。如果您想要返回一些可能为空的内容,请考虑将其包装在Optional
中。对于创建Optional
(而不是从调用中获取一个)并在同一链的末尾将其解包的代码要持怀疑态度。
我相信现在已经很清楚了,它们涵盖了不同的用例。但让我来说明"而不是稍后在代码中的某个地方使用Optional":无论您做什么,都要确保在代码中检查所需的nullablity属性(可以是null
,也可以不是)。不要返回您认为不可能null
的东西,但事实证明这是因为您没有检查。如果发生这种情况,则不是Optional
的错误。
确定Objects.requireNonNullOrElse(str,"other string");
并考虑使用静态导入以使其更具可读性。
这篇关于对象与可选,哪个更可取?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!