使用 Optional.ofNullable 代替三元运算符是一种好习惯吗?

Is using Optional.ofNullable as a replacement for the ternary operator a good practice?

考虑这个表达式的用法:

String hi = Optional.ofNullable(sayHi()).orElse("-");

有效对应于这个三元表达式:

String hi = sayHi() != null ? sayHi() : "-";

Optional.ofNullable 与方法调用一起使用是一种好的做法吗?或者只是额外的冗长编码?


我认识到 Optional.ofNullable 实际上创建了一个变量并避免调用 sayHi() 方法两次。为了避免这个问题,您实际上可以创建一个额外的变量,但这会增加三元选项的冗长程度:

String hi = sayHi();
hi = hi != null ? hi : "-";

另一方面,如果 hi 不是 nullOptional.ofNullable 创建一个额外的 Optional 对象。所以肯定会有更多的开销。

所以使用这种类型的构造来代替三元构造似乎有一些优点和缺点。


顺便说一下:这是 Java 8 实现 Optional.ofNullable:

public static <T> Optional<T> ofNullable(T value) {
    return value == null ? empty() : of(value);
}

如果您要允许 Optional 进入您的工作流程,那么您应该考虑修改 sayHi() 方法,使其 returns Optional<String> 这将使结果更优雅:

hi = sayHi().orElse("-");

如果您不想将 Optional 引入您的工作流程(因为它确实会创建一个额外的对象来包含可选值),那么您最好坚持使用简单的空值检查和三元运算符.

关于 Optional 的性能成本(例如增加垃圾收集),您需要分析您的应用程序并确定这是否是一个真正的问题。

此外,如果您对 String 最感兴趣,请注意 Objects.toString(Object, String) 方法,如果对象为 null,该方法 return 默认值:

hi = Objects.toString(hi, "-");

这比手动编写代码更简洁、更优雅。

每当我想到将可选 API 用于特定目的时,我总是提醒自己它的目的是什么以及为什么将它带入 JDK,即

Optional in 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 this is overwhelmingly likely to cause errors - Stuart Marks

Optional 主要关注可能有或可能没有 return 值的 return 类型。

像在您的这个特定示例中那样过度使用此构造只会导致额外的内存分配和 GC 开销。

我会保持简单,而不是:

String hi = sayHi();
if(hi == null) hi = “-“;
...

Is this usage of Optional.ofNullable with a method call a good practice?

Conceptually,这是一种不好的做法。基本思想是表示缺少 return 值,而不是包装可能是 null 的所有内容。我强烈反对这种用法。

Or just extra verbose coding?

在我看来,让您的代码更时尚的尝试失败了。 ("Look, we are using brand-new Optional from Java 8!")

相比简洁,我更喜欢可读性和清晰度。

这种 Optinal 用法不清晰,但提出了问题:

为什么要包装变量?
你打算用这个 Optional 做什么?
下面会是used/returned吗

它也不简洁:你的第二行甚至更短。

To avoid this problem you actually could create an extra variable but this adds to the verbosity of the ternary option.

您没有创建额外的变量。单行版本可以是:

String hi = (hi = sayHi()) != null ? hi : "-";

不过,你的两行建议绝对没问题:

String messageContent = sayHi();
String hi = messageContent != null ? messageContent : "-";

我认为这主要是个人品味问题。

在我看来,只 return 一个 Optional<String> 并让调用者处理缺失值会更有意义。

可选,作为 monadic 类型,可以利用更多,而不仅仅是获得 alt-value。

另一方面,您的 operator 似乎足够简洁,如果始终如一地使用它可能很实用。

我认为性能不是这里的大问题。

简而言之:避免 Optional 类型。 return 类型上 Optional 的主要论点是 "It's too easy for clients to forget to handle the possibility of a null return value. Optional is ugly and in your face, so a client is less likely to forget to handle the possibility of an empty return value. Everywhere else, programmers should continue to use normal references, which might be null."

我写了一篇关于使用 Java 的 Optional 类型优缺点的讨论:Nothing is better than the Optional type.

在 JDK 9 或更高版本中,使用此:

String hi = Objects.requireNonNullElse(sayHi(), "-");

这避免了在使用三元运算符时必须重复 sayHi(),或者将其值分配给在三元中重复使用的局部变量。这可能是一个小的改进。它还回避了是否使用 Optional 的问题。 :-)