java.util.Objects vs可选哪个更好?

Ant*_*iuc 16 java optional java-9

java.util.Objects类被延长了一些新的方法

对象#requireNonNullElse

分别

对象#requireNonNullElseGet() in Java-9.

如果第一个参数为非null,则它们将返回第一个参数,否则返回非null的第二个参数或者supplier.get()的非null值

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

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

jshell> Objects.requireNonNullElseGet(nullStr,() -> "lorem ipsum");
$14 ==> "lorem ipsum"
Run Code Online (Sandbox Code Playgroud)

但是新功能与Optional#orElseOptional#orElseGetOptional类中已存在的功能重叠

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

jshell> Optional.ofNullable(nullStr).orElseGet(() -> "lorem ipsum");
$18 ==> "lorem ipsum"
Run Code Online (Sandbox Code Playgroud)

新方法Objects和相应Optional方法之间的唯一区别是供应商的第二个参数或值必须为非null否则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)
Run Code Online (Sandbox Code Playgroud)

Optional

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

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

如果我有遗留代码,例如:

String str = null; 
String result = str == null ? "other string" : str;
Run Code Online (Sandbox Code Playgroud)

这只是方法内部的简单检查.我想使用最新的语言功能重新考虑它.现在要记住两者之间的区别Optional.orElse ,Objects.requireNonNullOrElse哪个更好?

result = Optional.ofNullable(str).orElse("other string");
Run Code Online (Sandbox Code Playgroud)

要么

result = Objects.requireNonNullOrElse(str,"other string);
Run Code Online (Sandbox Code Playgroud)

Nic*_*lai 20

你问题的最短答案"哪个更好?" 是所有时间最喜欢的开发商"看情况",因为Objects::requireNonNullElseOptional覆盖不同的使用情况.

两种选择

在回答你的问题之前,我想先介绍两种选择.

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
Run Code Online (Sandbox Code Playgroud)

你可能会认为它是不同的requireNonNullElseGet因为它可能会调用一个函数,取决于某个状态,可能会返回null或不返回.这是真的,我认为它已被考虑但requireNonNull...如果三个案例中的一个实际上允许调用的最终结果null即使名称说明必需非null,API也会非常奇怪.

Optional

Optional 在返回null极有可能导致NPE的情况下被设计为返回参数(就像Stream首次使用它的终端操作一样).虽然有些开发人员更喜欢在更多情况下使用它(比较Stephen Colebourne的实用方法我的严格方法),但没有人真正建议在演示中使用它:

Optional.ofNullable(nullStr).orElse(null);
Optional.ofNullable(nullStr).orElseGet(() -> null);
Run Code Online (Sandbox Code Playgroud)

Optional是一种在类型系统中表达某些东西可能会丢失的方法 - 它不是if- null-checks 的替代方案.从某种意义上说,orElse或者orElseGet是后门Optional进入可空类型的世界,有时null只是你想要使用的东西,如果不存在某些东西,那么它们null作为一个论点(或供应商的结果)接受是有意义的.

你的问题

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

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

从概念上讲,这将违背Optional应该使用的内容.但是,正如其他人所提到的,这将是一个向后不兼容的变化,因为调用orElse(null)会突然抛出异常.

为什么他们没有引入一个新方法(如果第二个参数为null将抛出NPE)到Optional类?

只有在可以预期对现有代码进行大量改进时,才会扩展API.我在这里看不到.在许多情况下,orElse得到一个参数,调用者专门创建作为空选项的替代 - 很少需要进行额外的检查以验证它不是null.如果你真的需要,请致电orElse(requireNonNull(x)).

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

如果你有一个变量(无论是本地,参数还是字段),并且你想确保它不是null,请使用Objects.如果你想返回一些东西,可能是null,考虑将其包装Optional.要怀疑创建一个代码Optional(而不是一个形式的调用)并在同一个链的末尾展开它.

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

我现在很清楚,它们涵盖了不同的用例.但是让我解决"而不是稍后在代码中的某个地方,如使用Optional":无论你做什么,一定要检查代码中你想要的nullablity属性(可以null与否).不要归还你认为不可能的东西,null但事实证明是因为你没有检查.如果发生这种情况,那不是Optional错.

如果我有遗留代码,例如:

String str = null; 
String result = str == null ? "other string" : str;
Run Code Online (Sandbox Code Playgroud)

绝对Objects.requireNonNullOrElse(str,"other string);考虑使用静态导入使其更具可读性.