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

news2024/9/28 19:26:55

本文仅供学习交流使用!

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 类声明的冗长性。开发人员完全可以放弃它并坚持旧的使用方式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/688098.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SSMP整合案例(7) MybatisPlus快速service业务层开发

上文 SSMP整合案例(6) 业务service层逻辑编写我们创建并编写了service业务层代码 但是 这样一个一个去写 确实是有点麻烦 重复性工作 但其实这个已经有人帮我们考虑好了 MP就帮我们做了一个 service快捷开发的方式 我们在项目中的service包下创建一个接口 叫 IBookService 其实…

fscan安装以及使用

windows安装 1.go语言下载。 下载msi版本&#xff0c;直接安装就可以不用配置环境变量&#xff0c;默认是帮你安装配合好的 https://go.dev/dl/ 2.配置go环境 使用默认配置的话&#xff0c;下载速度过慢&#xff0c;导致无法完成编译。故需要配置代理。 在cmd命令行中…

RocketMQ --- 基础篇

一、MQ介绍 1.1、为什么要用MQ 消息队列是一种“先进先出”的数据结构 其应用场景主要包含以下3个方面 1.1.1、应用解耦 系统的耦合性越高&#xff0c;容错性就越低。以电商应用为例&#xff0c;用户创建订单后&#xff0c;如果耦合调用库存系统、物流系统、支付系统&…

Shapley值法介绍及实例计算

Shapley值法介绍及实例计算 为解决多个局中人在合作过程中因利益分配而产生矛盾的问题,属于合作博弈领域。应用 Shapley 值的一大优势是按照成员对联盟的边际贡献率将利益进行分配,即成员 i 所分得的利益等于该成员为他所参与联盟创造的边际利益的平均值。 本文从Shapl…

【裸机开发】EPIT 定时器 —— 按键消抖

实际工程中&#xff0c;不能直接通过延时来消抖 ! 这里我们采用定时器来消抖&#xff0c;这也是内核处理消抖的一种方式。 目录 一、基本原理 1、延时消抖的弊端 2、定时器消抖原理 二、按键消抖实现 1、按键中断 2、定时器中断 三、附加&#xff1a;按键 / 定时器中断初…

熊哥保佑你 计算机组成原理复习

移码是符号位取反 . . Cache——主存地址映像&#xff1a; 全相联&#xff1a;块号字块内地址 直接映射&#xff1a;标记行号字块内地址 组相联&#xff1a;标记组号字块内地址 一个单元一个字节 2路组相联&#xff1a; 全相联&#xff1a; 直接映射&#xff1a; . …

代码随想录算法训练营第四十七天| 198.打家劫舍、 213.打家劫舍II 、 337.打家劫舍III

打家劫舍 题目链接&#xff1a;力扣 确定dp数组&#xff08;dp table&#xff09;以及下标的含义 dp[i]&#xff1a;截至到i位置的房屋&#xff0c;最多可以偷窃的金额为dp[i]。确定递推公式 决定dp[i]的关键因素就是第i房间偷还是不偷。如果偷第i房间&#xff0c;那么dp[i] …

Ceph分布式存储系统搭建

目录 安装部署示例 &#xff08;一&#xff09;准备环境 1). 设置主机名 2). 关闭防火墙 3).添加sdb磁盘并格式化 4).配置hosts解析文件 5).配置免密登录 6).同步时区 7). 安装 Ceph 包 &#xff08;二&#xff09;创建 Ceph 集群 1、 安装ceph-deploy管理工具 2、 …

【C++】STL——string类的基本介绍、string常见的使用、string类的接口说明、string类的容量操作

文章目录 1.C语言的字符串2.C标准库中的string类2.1string类2.2string类的常用接口说明2.3string类对象的容量操作 1.C语言的字符串 在C语言中&#xff0c;字符串被表示为字符数组。C语言中的字符串以’\0’字符&#xff08;null字符或字符串结束符&#xff09;结尾&#xff0c…

了解 Splashtop 的多层安全防护措施

随着技术的进步&#xff0c;如何确保数据安全也越来越重要。Splashtop 作为行业领先的远程访问软件供应商&#xff0c;对这一点非常了解。Splashtop 基于信任、客观性、监控和隐私搭建安全框架&#xff0c;致力于保护所有数据交互和用户设备。 了解 Splashtop 安全性的核心 S…

图像色彩增强相关论文阅读-Representative Color Transform for Image Enhancement(ICCV2021)

文章目录 Representative Color Transform for Image EnhancementAbstractIntroductionRelated workMethod实验Conclusion Representative Color Transform for Image Enhancement 作者&#xff1a;Hanul Kim1, Su-Min Choi2, Chang-Su Kim3, Yeong Jun Koh 单位&#xff1a;S…

MySQL调优系列(八)——事务和锁分类

一、事务是什么 事务是逻辑上的一组操作&#xff0c;要么都执行&#xff0c;要么都不执行。 sql语句如下&#xff1a; # 开启事务 START TRANSACTION; # 多条 SQL 语句 SQL1,SQL2... ## 提交事务 COMMIT;二、事务的特性&#xff08;ACID&#xff09; 原子性&#xff08;Atom…

线上商城开发都有哪些方法?费用多少

随着如今网络环境的愈发成熟&#xff0c;人们的消费习惯开始逐渐向线上迁移&#xff0c;为了能满足此种需求&#xff0c;企业商家都开始了线上商城的建设&#xff0c;希望能借助网络的力量促进自身的发展&#xff0c;创造更高的盈利空间&#xff0c;那么如何搭建一个线上商城呢…

Zookeeper 从安装到应用

博主介绍&#xff1a; ✌博主从事应用安全和大数据领域&#xff0c;有8年研发经验&#xff0c;5年面试官经验&#xff0c;Java技术专家✌ Java知识图谱点击链接&#xff1a;体系化学习Java&#xff08;Java面试专题&#xff09; &#x1f495;&#x1f495; 感兴趣的同学可以收…

GPIO模拟时序控制外设3——AT24C02

文章目录 前言AT24C02简介引脚介绍器件寻址寻址流程器件地址的组成其他I2C器件的地址组成 通信流程1.完整的传输过程2.初始化管脚3.起始信号4.停止信号5.MCU发送8位数据5.MCU接收应答位6.MCU接收八位数据7.MCU发送应答位 AT24C02写一个字节AT24C02读一个字节实现的效果 总结 前…

如何利用VS打包C++程序

如何将VS开发的C程序打包发给别人使用呢&#xff1f;话不多说&#xff0c;跟随以下步骤即可完成&#xff1a; 打包步骤 一.安装插件1.项目-->扩展-->管理扩展2.搜索-->下载3.下载完毕-->关闭VS4.Modify-->End Tasks&#xff08;跳过&#xff09;-->完成 二.配…

5.用python写网络爬虫,动态内容

目录 ​​​​​​​前言 5.1 动态网 页 示例 5.2 对动态网页进行逆向工程 5.2.1 边界情况 5.3 渲染动态网页 5.3.1 PyQt还是PySide 5.3.2 执行 JavaScript 5.3.3 使用WebKit与网站交互 1 . 等待结果 2. 渲染类 5.3.4 Selenium 5.4 本章小结 前言 根据联合国全球 网站可…

《诸神之眼:Nmap网络安全审计技术揭秘》读书笔记

《诸神之眼&#xff1a;Nmap网络安全审计技术揭秘》读书笔记 作者&#xff1a;李华峰 ◆ 前言 NSE是Nmap中革命性的创新。通过Nmap强大的脚本引擎&#xff08;NSE&#xff09;&#xff0c;每一个用户都可以向Nmap中添加自己编写的代码&#xff0c;从而将Nmap打造成用户自由定制…

Ansys Speos | material library 材料库提升仿真效率

概述 Speos 在不断更新细节功能的同时&#xff0c;不断地优化材料属性应用过程&#xff0c;旨在帮助用户在相同的项目或是不同的项目之间通用材料属性定义&#xff0c;甚至扩展到公司内部不同的设计人员之间数据的通用&#xff0c;减少光学材料属性定义花费时间&#xff0c;提升…

CMO:释放生成式人工智能的潜力,将营销和销售提升到新水平

生成式AI如ChatGPT正在迅速彻底改变全球业务运营。不仅深刻地重塑了全球商业格局&#xff0c;而且从根本上重新构想了CMO的责任&#xff0c;以适应新的范式。随着人工智能继续推动更高的效率、有效性和大规模创新的新浪潮&#xff0c;CMO有机会带头利用营销AI来加速和加强营销策…