Java中的记录类型(附实例)

2020年3月发布的JDK 14引入了记录(预览语言特性),它为声明主要目的是保存数据的类提供了一种紧凑的语法。在记录中,所有低级的、重复的、容易出错的代码都像构造函数、访问器和utlity方法,如equals(),hashCode(),toString() ,都是根据记录的状态描述自动派生的。

前提条件

你需要启用预览功能的JDK 14:

了解如何使用SDKMAN管理多个Java SDK!轻松实现。

记录声明

记录有一个名称和状态描述。状态描述声明了记录组成部分和可选的主体:

record Owner(String name, String address, String city, String telephone) {}

record PetType(String name) {}

record Pet(LocalDate birthDate, PetType type, Owner owner) {}
复制代码

记录的表示方法是机械地、完全地从状态描述中衍生出来的,其成员如下:

  • 一个private final 每个组件的字段
  • 每个组件有一个public 读取访问方法,其名称和类型与组件相同(例如:owner.name(),owner.address() )。
  • 一个public 构造函数
  • 一个equals() 的实现和hashCode()
  • toString() 的实现。

基本行为通过下面的测试来证明:

class Java14RecordTests {

    @Test
    void recordAccessors() {

        var owner = new Owner("John Doe", "110 W. Liberty St.", "Madison", "6085551023");

        assertThat(owner.name()).isEqualTo("John Doe");
        assertThat(owner.address()).isEqualTo("110 W. Liberty St.");
        assertThat(owner.city()).isEqualTo("Madison");
        assertThat(owner.telephone()).isEqualTo("6085551023");

    }

    @Test
    void recordEqualsAndHashCode() {

        var pet1 = new Pet(
                LocalDate.of(2019, 1, 1), 
                new PetType("dog"), 
                new Owner("John Doe", null, null, null)
        );
        var pet2 = new Pet(
                LocalDate.of(2019, 1, 1), 
                new PetType("dog"), 
                new Owner("John Doe", null, null, null)
        );

        assertThat(pet1).isEqualTo(pet2);
        assertThat(pet1.hashCode()).isEqualTo(pet2.hashCode());

    }

    @Test
    void recordToString() {
        var pet = new PetType("dog");
        assertThat(pet.toString()).isEqualTo("PetType[name=dog]");
    }
}
复制代码

限制条件

Record是一个受限制的类的形式,其限制是:

  • 记录不能扩展任何其他类
  • 任何其他被声明的字段必须是静态的
  • 记录的组件是隐含的最终的。

其他行为

除了上述限制外,记录的行为与普通的类一样。

  • 记录可以声明实例和静态方法、静态字段、静态初始化器:
record Owner(String name, String address, String city, String telephone) {
    /* Static initializer */
    static {
        NONE = "N/A";
    }
    /* Static fields are allowed, both private and public */
    private static String NONE;

    /* Records may have static methods */
    public static Owner anOwner(String name) {
        return new Owner(name, NONE, NONE, NONE);
    }
}
复制代码
  • 记录可以声明构造函数,也可以声明紧凑构造函数。紧凑构造函数可以访问记录的组件:
record Pet(LocalDate birthDate, PetType type, Owner owner) {
    /* `Compact` constructor */
    public Pet {
        requiresNotNull("birthDate", birthDate);
        requiresNotNull("type", type);
        requiresNotNull("owner", owner);
    }
    
    public Pet(LocalDate birthDate, PetType type) {
        this(birthDate, type, null);
    }

    /* Records may have instance methods */
    private void requiresNotNull(String name, Object obj) {
        if (Objects.isNull(obj)) {
            throw new IllegalArgumentException(name + " can't be null");
        }
    }
}
复制代码
  • 记录可以覆盖所有的标准方法。equals(),hashCode()toString()
  • 记录可以实现接口
  • 记录可以被注解

...以及更多。

源代码

这篇文章的源代码可以在Github上找到:https://github.com/kolorobot/java9-and-beyond

参考文献

猜你喜欢

转载自juejin.im/post/7125711495773552670