java.util.Objects类扩展了许多新方法
分别
Java-9
中的Objects#requireNonNullElseGet()。
如果第一个参数为非null,则返回第一个参数,否则返回非null的第二个参数或者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
:< / p>
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
如果我有遗留代码,例如:
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);
答案 0 :(得分:18)
您问题的最短答案&#34;哪个更好?&#34;是开发人员最喜欢的&#34;它取决于&#34;因为Objects::requireNonNullElse
和Optional
涵盖了不同的用例。
在回答你的问题之前,我想先介绍两种选择。
Objects::requireNonNullElse
Objects::requireNonNull
确保调用的结果永远不为null(因此名称)。它通常用于简洁地验证构造函数或方法参数,并允许读者一目了然地判断返回值所分配的变量不能为空。
因此,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
,具体取决于某个州。这是真的,我认为它被考虑了,但如果三个案例中的一个实际上允许调用的最终结果为requireNonNull...
,那么null
API将非常奇怪,即使名称说要求非空。
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
作为论据(或供应商的结果)是有道理的。
现在我们有了解答问题所需的内容:
为什么JDK开发人员没有更新Optional类中的现有方法?
从概念上讲,这将违背orElse(null)
应该使用的内容。但是,正如其他人所提到的,这将是一个向后不兼容的变化,因为对orElse
的调用会突然抛出异常。
为什么他们没有引入一个新方法(如果第二个参数为null则将NPE抛出)到Optional类?
只有在可以预期对现有代码进行大量改进时才会扩展API。我在这里看不到。在许多情况下,null
会得到一个参数,调用者专门为空选项创建一个替代方案 - 很少需要进行额外检查以验证它不是orElse(requireNonNull(x))
。如果您真的需要,请致电Objects
。
我们现在应该使用什么可选或对象?
如果您有变量(无论是本地变量,参数还是字段),并且您想确保它不为空,请使用Optional
。如果你想返回一些可能为null的东西,可以考虑将它包装在Optional
中。怀疑创建null
的代码(而不是通过调用形成一个代码)并在同一个链的末尾展开它。
新方法是否使对象比Optional更可取,因为它们会立即抛出NPE,而不是稍后在代码中的某个地方抛出,比如可选?
我现在很清楚,它们涵盖了不同的用例。但是,让我解决&#34;而不是稍后在代码中的某个地方,例如使用Optional&#34;:无论你做什么,请确保在你的代码中检查你想要的nullablity属性(可以是null
)。不要归还你认为不能Optional
的东西,但结果却是因为你没有检查。如果发生这种情况,那就不是String str = null;
String result = str == null ? "other string" : str;
的错误。
如果我有遗留代码,例如:
Objects.requireNonNullOrElse(str,"other string);
绝对{{1}}并考虑使用静态导入使其更具可读性。
答案 1 :(得分:4)
为什么JDK开发人员没有更新Optional类中的现有方法?
因为这会引入一个突破性的变化,会破坏许多现有的程序,并且因为该方法应该允许在需要时变为空。
为什么他们没有引入一个新方法(如果第二个参数为null将抛出NPE)到Optional类?
可能是因为这会使API更加复杂和臃肿,没有明显的优势。如果要确保代码不会意外返回null,仍然可以使用requireNonNull包装结果。
我们现在应该使用什么可选或对象?
如果需要从方法返回的可选项中提取值,请使用Optional的方法。如果要确保对于不应为null的方法的参数,请遵守前提条件,请使用Object.requireXxx。 JDK设计者从未提倡使用Optional只是为了包装一个值并检查null。可选是返回值。
新方法是否使对象比Optional更可取,因为它们会立即抛出NPE,而不是稍后在代码中的某个地方抛出,比如可选?
请参阅前面的观点:您不要使用这些方法来做同样的事情。
答案 2 :(得分:3)
关键是:这两个方法签名明显不同:
public static <T> T requireNonNullElse(T obj, T defaultObj)
VS
public static <T> T requireNonNullElseGet(T obj, Supplier<? extends T> supplier)
第二种方法的javadoc为:
如果它是非null,则返回第一个参数,否则返回supplier.get()的非null值。
换句话说:它使用您在此处提供的供应商。
因此,答案是:在想要与供应商合作的情况下,您使用第二个版本;否则你只需要更简单的&#34;采用&#34;不那么复杂的方法的版本&#34;参数。
背后的理由:当你决定两个选项时,你更喜欢那个更容易/更少读者惊喜的#34;使用。换句话说:为什么你想在没有供应商的情况下提供供应商。
关于使用Optionals - 请注意,他们的主要目标将用于返回类型;不作为方法参数(参见here进一步阅读)。
然后:更新已交付的类中的现有方法&#34;到字段&#34;几乎总是不行。你绝对不会不想要改变已经公开并被客户使用的东西的语义;假设具体的语义。
答案 3 :(得分:0)
Q值。为什么JDK开发人员没有更新Optional类中的现有方法?
一个。因为Optional
类旨在避免NPE。
Q值。为什么他们没有引入一个新方法(如果第二个参数为null将抛出NPE)到Optional类?
一个。同样的答案。
Q值。我们现在应该使用Optional或Objects?。
一个。都。 Objects
用于简单的“非空”检查,Optional
用于链式操作,例如map
,flatMap
,“过滤器”。
Q值。新方法是否使对象比Optional更可取,因为它们会立即抛出NPE而不是稍后在代码中的某个地方抛出,比如可选吗?
一个。取决于情况。如果您已经将Optional作为某些方法的返回值,那么最好使用Optional。
答案 4 :(得分:0)
所以主要的一点是,如果你喜欢使用ifs检查是否为null。如果你有一个方法可以接受可以为null值的参数,那么使用Objects会更有意义。使用Optional的唯一合理位置是验证对返回可选结果的方法的调用。
开发人员希望使用更多功能性的方法来检查空值,因此使用构造Optional.ofNullable
来实现此目的,这不是一个好习惯,因为它正在创建垃圾。