【Java】Java 纪录类(Record Class)及代码示例

本文仅供学习交流使用!

Java Record Class相关文章地址:

https://www.liaoxuefeng.com/wiki/1252599548343744/1331429187256353

https://www.baeldung.com/java-record-keyword

https://www.developer.com/java/java-record-class/

在这里插入图片描述

Java中的记录类是什么?

在处理 Java 项目时,作为开发人员,我们经常编写服务类、安全类或任何其他基本类。这些类本质上是功能性的。同样,程序员编写类的唯一目的通常是携带数据。例如,假设客户端从服务器请求一些数据,例如一个人的ID姓名,并且服务器用适当的数据进行响应。由于Java中一切都是对象,因此必须有某个类来承载数据。服务器将类的对象返回给客户端。请注意,该对象的唯一目的是将数据从服务器传送到客户端。

现在,编写这样一个数据类,即使它可能是一个简单的 POJO,也包含大量样板代码,例如私有字段、构造函数、getter setter 方法、hashCode() equals()toString ( )方法。由于 Java 语言的冗长性质,简单的载体类会变得繁重,包含大量不必要的代码。这些缺点导致引入了一种称为record的特殊类型的类。此类聚合(或保存)一组值,而无需编写样板代码,并充当数据对象的有效载体。

事实上,开发人员可以在没有记录类的情况下管理一切,就像我们长期以来所做的那样。记录类在便利性和效率方面将数据载体类重新定义到另一个水平。

我们经常用作数据载体的一个简单的 POJO 类可能包含大量的样板代码。下面是在 Java 中创建此类的代码示例:

package org.example;

import java.util.Objects;

public class Person {
    
    
    private int id;
    private String name;

    public Person() {
    
    
    }

    public Person(int id, String name) {
    
    
        this.id = id;
        this.name = name;
    }

    public int getId() {
    
    
        return id;
    }

    public void setId(int id) {
    
    
        this.id = id;
    }

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    @Override
    public boolean equals(Object o) {
    
    
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return getId() == person.getId() && getName().equals(person.getName());
    }

    @Override
    public int hashCode() {
    
    
        return Objects.hash(getId(), getName());
    }

    @Override
    public String toString() {
    
    
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

如何在 Java 中创建记录类

Java 中的 Record类由上下文相关关键字record支持。除非与记录声明一起使用,否则该关键字没有特殊含义。通常,在 Java 中使用以下语法声明记录:

record recordName(list-of-components) {
    
     
	//可选语句
}

请注意,该声明与 Java 中的典型类声明有显着不同。该声明非常类似于以关键字record开头,后跟记录名称的函数。该记录类的参数包含逗号分隔的组件列表。该组件列表指定记录将保存的数据。另请注意,记录的正文是可选的

现在,假设程序员想要创建上述person类的记录 - 开发人员可以使用以下 Java 代码示例声明该记录:

record Person(int id, String name){
    
    }

就是这样!我们准备创建此类的对象,如下所示:

Person p1 = new Person(1,Peter Parker);

在幕后,编译器自动提供存储数据所需的元素、构造函数、访问数据的 getter 方法、toString()equals()和`hashCode()方法,而无需程序员的任何干预。因此,以下是有效的代码,尽管我们没有明确编写任何此类内容:

// toString方法的使用
System.out.println(p1.toString()); 
// getter方法的表现形式
System.out.println(p1.name());  

package org.example;

record Person(int id, String name){
    
    }
public class App
{
    
    
    public static void main( String[] args )
    {
    
    
        Person p1 = new PersonRecord(1,"Peter Parker");
        Person p2 = new PersonRecord(2,"Spiderman");
        System.out.println(p1.toString());
        System.out.println(p1.equals(p2));
        System.out.println(p1.name());
    }
}

关于上面的代码示例,有几点需要注意:

  • 记录类提供的规范构造函数包含与组件列表相同的参数,并且按相同的顺序传递。传递的值会自动分配给记录字段。
  • 记录由new关键字实例化,就像在 Java 中创建任何其他对象一样。
  • 记录中的数据保存在私有最终字段中,并且只有一个 getter 方法。因此,记录中的数据是不可变的
  • 记录不能继承另一个类。但是,所有记录都隐式继承java.lang.Record。因此,它重写了Object类的equals()hashCode()toString()方法。
  • 所有记录声明都是最终的,因此不能延期。
  • 然而,一条记录可以实现一个或多个接口。
  • 除组件列表之外的任何其他字段都必须声明为静态。

Java 中的规范构造函数

规范构造函数具有特定于 Java 中记录类构造的预定义形式。但是,有两种方法可以声明我们自己的实现。在 Java 中声明规范构造函数的第一种方法是使用以下代码:

record Invoice(String id, float amount) {
    
    
    static String prefix = String.valueOf(Calendar.getInstance().get(Calendar.YEAR))
            +String.valueOf(Calendar.getInstance().get(Calendar.MONTH)+1);
  
    public Invoice(String id, float amount){
    
    
        this.id=prefix+id.trim();
        this.amount=amount;
    }
}

另一种方法是声明一个紧凑的构造函数,其中签名的声明是隐式的。在这里,我们只需提供记录名称作为构造函数,不带任何参数。这种类型的构造函数具有所有参数的隐式声明(与记录组件相同),并自动分配给传递给记录组件的值。另请注意,在紧凑构造函数中,我们不使用 this 关键字。

record Invoice(String id, float amount) {
    
    
    static String prefix = String.valueOf(Calendar.getInstance().get(Calendar.YEAR))
            +String.valueOf(Calendar.getInstance().get(Calendar.MONTH)+1);
    public Invoice{
    
    
        id=prefix+id.trim();
        amount=amount;
    }  
}

Java 中的非规范构造函数

虽然有一个规范的构造函数就足够了,但程序员也可以声明一个非规范的构造函数,我们可能只想用默认值初始化记录字段的一个值。在这种情况下,开发人员可能会编写非规范的构造函数。非规范构造函数的关键要求是该构造函数*必须通过this关键字调用记录中的另一个构造函数。这是一个简单的例子:

record Invoice(String id, float amount) {
    
    
    static String prefix = String.valueOf(Calendar.getInstance().get(Calendar.YEAR))
            +String.valueOf(Calendar.getInstance().get(Calendar.MONTH)+1);
    public Invoice{
    
    
        id=prefix+id.trim();
        amount=amount;
    }

    public Invoice(String id){
    
    
        this(id,0.0f);
    }
}

同时使用规范构造函数和非规范构造函数来声明记录是完全有效的,并且记录可以具有的构造函数的数量没有限制,只要它是根据记录的规范设计的。

有关 Java 构造函数的更多信息,可阅读:如何在 Java 中使用构造函数

Java 记录类代码示例

下面是一个快速代码示例,展示了如何在 Java 中使用Record类、规范构造函数和非规范构造函数:

package org.example;

record Invoice(String id, float amount) {
    
    
    static String prefix = String.valueOf(Calendar.getInstance().get(Calendar.YEAR))
            +String.valueOf(Calendar.getInstance().get(Calendar.MONTH)+1);
    public Invoice{
    
    
        id=prefix+id.trim();
        if(amount<0)
            throw new IllegalArgumentException("-ve values not allowed");
        amount=amount;
    }
    public Invoice(String id){
    
    
        this(id,0.0f);
    }

}
public class App
{
    
    
    public static void main( String[] args )
    {
    
    
        float[] amt = {
    
    400.00f,600.00f,300.00f,700.00f,600.00f};
        Invoice[] invoice = new Invoice[5];
        for(int i=0;i<invoice.length;i++)
            invoice[i] = new Invoice(String.valueOf(i+1), amt[i]);
        for(int i=0;i<invoice.length;i++)
            System.out.println(invoice[i].toString());
    }
}

Record类的特点

  • 带有全部参数的构造方法
  • public 访问器
  • toString(),hashCode(),equals()
  • 无 set,get 方法。没有遵循 Bean 的命名规范
  • final 类,不能继承 Record,Record 为隐士的 final 类。除此之外与普通类一样
  • 不可变类,通过构造创建 Record
  • final 属性,不可修改  不能声明实例属性,能声明 static 成员

最后

Java 的Record类除了作为数据载体之外,还可以有许多创新的用例。隐式使用java.lang.Record类的关键字record的引入为其添加了另一层便利。毕竟,它是一个方便的类,专门设计用作数据载体,根据 Java 语言规范,它打破了 POJO 类声明的冗长性。开发人员完全可以放弃它并坚持旧的使用方式。

猜你喜欢

转载自blog.csdn.net/m0_47015897/article/details/131401663