建议将Java 8中引入的Optional<T>类型主要用于返回类型和结果.因此,每当我在类字段或方法参数中使用它时,我都会在IntelliJ中收到警告:

Optional<?>用作字段/参数的类型.

但是,当我在Canonical构造函数中使用Optional<T>作为记录参数时,我没有收到此警告:

public record AuthenticationResult(
    boolean isAuthenticated,
    Optional<User> user,
    Optional<String> authorizationHeader)
{ } 

不使用Optional<T>个类型作为参数/字段的做法是否不适用于记录参数,因为该字段将始终作为记录的自动生成的getter方法的返回值进行访问?

或者是因为记录是一项新功能,此警告尚未实现,并且在记录中使用可选参数与用作方法参数或字段时具有相同的后果?

推荐答案

我会try 解释为什么当前版本的IntelliJ不会对具有可选字段的记录发出警告(这是IDE开发人员的问题).

在这篇文章中,我将讨论有关使用Optional的推荐实践的问题,特别是对Java 16唱片.

不使用Optional<T>个类型作为parameters/fields的做法不适用于record参数吗

首先,Optional不打算用作字段类型,因此Optional不实现Serializable(see).其次,记录是数据载体,它们的字段是final.因此,如果记录的初始选项为空,则它们在整个时间跨度内都将保持为空.

Usage of Optional

以下是来自Java和OpenJDK开发人员answer by @StuartMarks的一句话,关于Optional的用途:

Optional人中的第101人如下:

可选用于 为库101提供100,其中 显然需要表示"无结果",以及在哪里使用NULL 因为这极有可能导致错误.

OPTIONAL的唯一有效用法是从产生它的方法返回它.调用者应该立即解包可选参数(API为此提供了很多方法).但是,如果您传递可选对象并将其存储在某个地方,那么您所做的就不是一种好的做法.

Optional is not meant for

可选的是要使用的not meant:

  • 作为字段类型;
  • 作为方法参数的一种类型;
  • 要储存在一个Collection
  • 或用于执行null-checks.用Optional.ofNullable()替换显式null-check是一种反模式.

下面引用了Java语言架构师@Brian Goetz的回答 (Should Java 8 getters return optional type?):

当然,人们会为所欲为.

例如,您可能永远不应该将其用于 返回结果数组或结果列表;而不是返回 空数组或列表.你应该差不多never use分才是field分 关于某物或method parameter的.

另外,看看这answer by StuartMarks人,这里有一小段引述:

class field或数据 struct 中有Optional被认为是misuse of the API.首先,它违背了顶部所述的可选的主要设计目标.其次,它不会增加任何价值.

Records are Transparent carriers for Immutable data

带有可选字段的对象迫使处理它的人始终考虑通过getter获得的对象不是值,而是102,如果您盲目地对其调用get(),可能会抛出 NoSuchElementException.

此外,在记录中具有可选类型的字段与记录的一般概念相冲突.

下面是JEP 395人中Record的定义:

records,它们是充当transparent carriers for immutable data的类.可以将记录视为名义元组.

带有可选字段的记录不再是transparent,因为我们不能通过访问器方法直接从它获取值.

由于记录字段为immutable,因此将可能为空的选项存储为记录属性没有意义,这几乎与存储null-references相同.因为记录中的字段不能更改,所以空的可选项将保持为空,并且某些元组可能根本不包含有用的数据.

传递可选参数没有好处,将它们存储在记录中,以便在以后的某个时间点发现它们不包含实际数据.

相反,在创建记录之前,您必须从从现场某个地方获得的可选对象中提取value(如果存在).

Java相关问答推荐

具有额外列的Hibert多对多关系在添加关系时返回NonUniqueHealthExcellent

BiPredicate和如何使用它

为什么Java中的两个日期有差异?

为什么BasicComboBoxRenderer在文本不存在或文本为空的情况下设置两次文本?

在JavaFX项目中注册组合框的控件FX验证器时,模块系统出错

FALSE:它应该在什么时候使用?

无法了解Java线程所消耗的时间

Javadoc在方法摘要中省略方法

如何为JavaFX Spring Boot应用程序制作Windows/MacOS/Linux安装程序

try 将JSON字符串响应从API转换为映射字符串、对象>;时出错

有效的公式或值列表必须少于或等于255个字符

try 使用类来包含JSON响应

为什么在下面的Java泛型方法中没有类型限制?

无法使用Java PreparedStatement在SQLite中的日期之间获取结果

Java中HashSet的搜索时间与TreeSet的搜索时间

Java System.getProperty在哪里检索user.home?

让标签占用JavaFX中HBox的所有可用空间

Android上的SQLite:Android.database.SQLite.SQLiteReadOnlyDatabaseException:try 写入只读数据库(代码1032 SQLite_readonly_DBMOVED)

Java编译器是否进行了持续的折叠优化,以及如何进行判断?

Java 8 中 ByteBuffer 和 BitSet 的奇怪行为