可选<T>作为Java中的记录参数

Ama*_*l K 7 java record option-type java-17

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

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

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

public record AuthenticationResult(
    boolean isAuthenticated,
    Optional<User> user,
    Optional<String> authorizationHeader)
{ } 
Run Code Online (Sandbox Code Playgroud)

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

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

Ale*_*nko 14

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

在这篇文章中,我将解决有关使用建议实践的问题Optional,特别是 Java 16 Records。

Optional<T>不使用类型作为参数/字段的做法是否不适用于记录参数

首先,Optional不打算用作字段类型,因此Optional未实现Serializable请参阅参考资料)。其次,记录是数据载体,其字段是final。因此,如果记录使用空选项进行初始化,则它们在整个时间跨度内将保持为空。

可选的使用

以下引用了Java 和 OpenJDK 开发人员@StuartMarks 的回答关于用途:Optional

主要用途Optional如下:

Optional 旨在为库方法返回类型提供一种有限的机制,其中明确需要表示“无结果”,并且使用 null 极有可能导致错误。

Optional 的唯一有效用法是从它起源的方法返回它。调用者应该立即解压可选的(API 提供了很多方法)。但是,如果您传递可选对象并将其存储在某个地方,那么您所做的并不是一个好的做法。

可选并不意味着

可选并不意味着要使用:

  • 作为字段类型;
  • 作为方法参数的类型;
  • 存储在Collection;
  • 或用于执行空检查。用代替显式空检查Optional.ofNullable()是一种反模式。

以下是 Java 语言架构师@Brian Goetz的回答(Should Java 8 getters return optional type?):

当然,人们会做他们想做的事......

例如,您可能永远不应该将它用于返回结果数组或结果列表的内容;相反,返回一个空数组或列表。您几乎应该将其用作 某物的字段或方法参数

另外,看看StuartMarks 的这个答案,这里有一个小引用:

Optional类字段或数据结构中包含被视为对 API 的滥用。首先,它违背了顶部所述的可选的主要设计目标。其次,它没有增加任何价值。

记录是不可变数据的透明载体

具有Optional字段的对象会迫使处理它的人始终考虑到通过getter获得的对象不是一个值,而是可能为空的Optional NoSuchElementException如果你盲目地调用get()它,可能会抛出异常。

此外,记录中具有可选类型的字段与记录的一般概念相矛盾。

以下是JEP 395记录的定义:

记录,它们是充当不可变数据的透明载体的类。记录可以被认为是名义元组。

具有可选字段的记录不再是透明的,因为我们无法通过访问器方法直接从中获取值。

由于记录字段是不可变的,因此将可能为空的选项存储为记录属性是没有意义的,它几乎与存储空引用相同。由于记录中的字段无法更改,因此空选项将保持为空,并且某些元组可能根本不包含有用的数据。

传递选项、将它们存储在记录中以便稍后发现它们不包含实际数据并没有任何优势。

相反,您必须在创建记录之前从现场某处获取的可选对象中提取值(如果存在)。

  • 空值在最终字段中保持为空是绝对有效的。同样地,在分配给最终字段后,null 保持为 null 是完全可以的。这种保持空虚的论点根本没有道理。 (3认同)