专业编程基础技术教程

网站首页 > 基础教程 正文

Java修炼终极指南:83. 声明一个Java记录

ccvgpt 2024-11-19 02:14:59 基础教程 7 ℃


在深入探讨Java记录之前,让我们思考一下我们通常是如何在Java应用程序中携带数据的。你说得对……我们定义简单的类,包含所需的实例字段,并通过这些类的构造函数用我们的数据填充这些字段。我们还提供了一些特定的getter方法,以及流行的equals()、hashCode()和toString()方法。此外,我们创建了这些类的实例,这些实例包装了我们宝贵的数据,并在应用程序的各个任务中传递它们。例如,以下类携带了关于甜瓜的数据,如甜瓜类型和它们的重量:

Java修炼终极指南:83. 声明一个Java记录

public class Melon {
  private final String type;
  private final float weight;
  public Melon(String type, float weight) {
    this.type = type;
    this.weight = weight;
  }
  public String getType() {
    return type;
  }
  public float getWeight() {
    return weight;
  }
  // hashCode(), equals(), 和 toString()
}


你应该非常熟悉这种传统的Java类和这种繁琐的仪式,所以没有必要坚持这段代码。现在,让我们看看如何使用Java记录的语法糖来完成完全相同的事情,这大大减少了之前的仪式:

public record MelonRecord(String type, float weight) {}


Java记录自JDK 14起作为特性预览提供,并在JDK 16中作为JEP 395发布和关闭。这一行代码给了我们与前面Melon类相同的行为。在幕后,编译器提供了所有这些构件,包括两个私有final字段(type和weight)、一个构造函数、两个与字段同名的访问器方法(type()和weight()),以及包含hashCode()、equals()和toString()的三部曲。我们可以通过在MelonRecord类上调用javap工具来轻松查看编译器生成的代码:

图4.1 - Java记录的代码

请注意,这些访问器的名称不遵循Java Bean约定,因此没有getType()或getWeight()。有type()和weight()。然而,你可以显式地编写这些访问器或显式添加getType()/getWeight() getter - 例如,为了暴露字段的防御性副本。所有这些内容都是基于我们声明记录时给出的参数(type和weight)构建的。这些参数也被称为记录的组件,我们说记录是构建在给定组件上的。编译器通过record关键字识别Java记录。这是一种特殊的类(就像枚举是Java类的一种特殊类型),被声明为final,并且自动扩展java.lang.Record。实例化MelonRecord与实例化Melon类相同。以下代码创建了一个Melon实例和一个MelonRecord实例:

Melon melon = new Melon("Cantaloupe", 2600);
MelonRecord melonr = new MelonRecord("Cantaloupe", 2600);


Java记录并不是可变JavaBean类的替代品。此外,你可能会认为Java记录只是携带不可变数据或不可变状态的简单透明方法(我们说“透明”,是因为它完全暴露了其状态,我们说“不可变”,是因为该类是final的,它只有私有final字段,并且没有setter)。在这个背景下,我们可能会认为Java记录不太有用,因为它们只是重叠了我们可以通过Lombok或Kotlin获得的功能。但正如你将在本章中看到的,Java记录不仅仅是这样,它提供了几个在Lombok或Kotlin中不可用的功能。此外,如果你进行基准测试,你会发现使用记录在性能方面有显著优势。

Tags:

最近发表
标签列表