Java record类用法简介

参考资料

  1. Java 16 新特性:record类
  2. 新特性Record最全用法总结—动力节点总结
  3. Javaのレコードクラス
  4. 从头学Java17-Stream API(二)结合Record、Optional

目录

  • 一. 介绍
  • 二. 基本语法
  • 三. 各种特性示例
    • 3.1 准备
    • 3.2 创建,属性,方法,内部record类
    • 3.3 反射
    • 3.4 记录模式(Record Patterns)
    • 3.5 组件属性浅层不可变
  • 四. 适用场景


一. 介绍

  • 是一种特殊的java类,在Java16中正式出现,用于创建一个不可变的类。该类一经创建并赋值后,就不可再改变了。
  • 类以及所有的属性都是final修饰的, Record类不能被继承。
  • 可用于创建一个简单的数据传输对象(DTO),用来传输数据。
  • record类会自动生成,全参构造方法,hashCode()方法,equals()方法,toString()方法和用来获取数据的方法。
  • 注意,在record类对象创建后,只能get数据,无法set数据,这一点和普通的POJP不同。
  • 在只读取数据的场景中,可以代替lombok

二. 基本语法

  • 支持实现接口,不支持继承
  • 支持静态变量,静态代码块,静态方法
  • 支持注解
  • 不支持成员变量和初始化代码块
  • 可内部嵌套record,嵌套的record是static状态的
    • 内部record只能访问外部record的静态方法和变量
  • 可通过反射来获取record的信息

⏹基本构造示例

在这里插入图片描述


三. 各种特性示例

3.1 准备

⏹接口

public interface S002Api {Map<String, String> getS001Data();
}

⏹创建一个record类,该类有内部record类,并且实现了接口

import java.util.List;
import java.util.Map;
import org.springframework.util.ObjectUtils;public record StudentRecord(Integer id, String name, List<String> addressList) implements S002Api {// 静态变量public static Integer money;// 只允许静态变量,成员变量变量会报错// String food = "汉堡";// 不支持初始化代码块/* {}*/// 静态代码块static {money = 100;}// 构造方法的简单写法,若在赋值时,不需要进行二次数据处理,可以简化为下面这种写法// record会给我们自动赋值public StudentRecord {// 在构造对象时,对数据进行校验if (ObjectUtils.isEmpty(addressList)) {throw new RuntimeException("addressList不能为空");}}// 静态方法public static void printMsg1() {System.out.println("Hello world! printMsg1");}// 非静态方法public void printMsg2() {System.out.println("Hello world! printMsg2");}// 实现接口中的方法@Overridepublic Map<String, String> getS001Data() {return Map.of("key1", "value1");}// record类的内部可以嵌套record类,该类是静态类,static可省略public static record InfoRecord(String car, String pet) {// record类默认会生成构造方法,但我们可以根据需要对其进行修改public InfoRecord(String car, String pet) {this.car = "/__" + car + "__/";this.pet = "/__" + pet + "__/";}public String getMsg() {// 因为内部record类是static的,所以只能调用外部record类中的静态方法printMsg1();// printMsg2();return "{num: 10}";}}
}

3.2 创建,属性,方法,内部record类

public void run(String... args) throws Exception {// 创建Record类对象StudentRecord studentRecord1 = new StudentRecord(120, "Jmw", List.of("地球", "宇宙"));System.out.println(studentRecord1);  // StudentRecord[id=120, name=Jmw, addressList=[地球, 宇宙]]// 调用静态方法StudentRecord.printMsg1();  // Hello world! printMsg1// 调用非静态方法studentRecord1.printMsg2();  // Hello world! printMsg1// 获取静态变量System.out.println(StudentRecord.money);  // 100// 获取类的属性System.out.println(studentRecord1.id());  // 120System.out.println(studentRecord1.addressList());  // [地球, 宇宙]// 创建内部Record类对象InfoRecord infoRecord = new StudentRecord.InfoRecord("丰田", "狗");System.out.println(infoRecord);  // InfoRecord[car=/__丰田__/, pet=/__狗__/]// 获取内部Record的方法String msg = infoRecord.getMsg();System.out.println(msg);  // {num: 10}
}

3.3 反射

public void run(String... args) throws Exception {// 创建一个Record类,因为Record类实现了S002Api接口,所以类型可以指定为S002ApiS002Api s002ApiObj = new StudentRecord(130, "Fyh", List.of("银河", "火星"));// 判断是否是Record类boolean isRecord = s002ApiObj.getClass().isRecord();System.out.println(isRecord);  // true// 获取该Record上所有的ComponentRecordComponent[] recordComponents = s002ApiObj.getClass().getRecordComponents();for (RecordComponent recordComponent : recordComponents) {System.out.println(recordComponent);}/*java.lang.Integer idjava.lang.String namejava.util.List addressList*/
}

3.4 记录模式(Record Patterns)

  • 配合instanceof使用,用于类型转换时,直接获取组件值(属性值)
  • 类似于JavaScript中的解构赋值
public void run(String... args) throws Exception {// 通过反射S002Api s002ApiObj = new StudentRecord(130, "Fyh", List.of("银河", "火星"));// 将接口转换为Record对象之后,才能通过转换之后的对象获取if(s002ApiObj instanceof StudentRecord) {// 手动进行对象转换StudentRecord obj = (StudentRecord)s002ApiObj;System.out.println(obj.id());  // 130System.out.println(obj.name());  // FyhSystem.out.println(obj.addressList());  // [银河, 火星]}// Java21中的新语法,类似于javascript中的解构赋值if(s002ApiObj instanceof StudentRecord(Integer id, String name, List<String> addressList)) {System.out.println(id);  // 130System.out.println(name);  // FyhSystem.out.println(addressList);  // [银河, 火星]}
}

3.5 组件属性浅层不可变

  • 组件类型为基本数据类型的时候,不可变。
  • 若类型为引用类型的话,深层是可变的。
public void run(String... args) throws Exception {// 定义一个简单的recordrecord JmwInfo(String id, String[] address) {};JmwInfo jmwInfo = new JmwInfo("10", new String[] {"地球", "月球"});// 在编译阶段就报错,无法被修改// jmwInfo.id = "20";System.out.println(jmwInfo.address[0]);  // 地球jmwInfo.address[0] = "日本";System.out.println(jmwInfo.address[0]);  // 日本
}

四. 适用场景

  • 作为数据载体,例如DTO,VO等
  • 适用于函数式编程

⏹有如下字符串,现在要求转换为java对象,保留20以上的,姓相同的分在一组

String teacherInfo = """张三,18李四,20王五,19赵六,20张四,22张之维,100王八,15""";
public void run(String... args) throws Exception {// 定义一个简单的recordrecord Teacher(String name, Integer age) {};// 根据换行符切割字符串String[] teacherArrays = teacherInfo.split("\n");// 构造Teacher对象的函数Function<String, Teacher> createTeacher = (line) -> {String[] split = line.split(",");// 在此处创建了record的Teacher类return new Teacher(split[0], Integer.parseInt(split[1]));};Map<Character, List<Teacher>> result = Arrays.stream(teacherArrays)// 先将数据处理为Teacher对象.map(createTeacher)// 过滤出 >= 20 的数据.filter(teacher -> teacher.age() >= 20)// 根据姓来分组.collect(Collectors.groupingBy(teacher -> teacher.name.charAt(0)));System.out.println(result);/*{张=[Teacher[name=张四, age=22], Teacher[name=张之维, age=100]], 赵=[Teacher[name=赵六, age=20]], 李=[Teacher[name=李四, age=20]]}*/
}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL 社区版 安装总结

很早就安装过MySQL&#xff0c;没有遇到过什么问题&#xff0c;直接next就行了&#xff0c;这次在新电脑上安装却遇到了一些问题&#xff0c;记录一下。 安装的是MySQL社区版&#xff0c;下载地址是www.mysql.com&#xff0c;进入后选择DOWNLOAD页面&#xff0c;选择MySQL Com…

对常见FTP客户端/服务器的调查与分析

前言 主要是想看看常见的服务器和客户端是如何实现协议中要求的功能的&#xff0c;。 比如RF959要求的记录结构&#xff08;Record Structure&#xff09;、页结构&#xff08;Page Structure&#xff09;、Block Mode、Compress Mode&#xff0c;看起来就很抽象。 实测发现…

快速入门深度学习9.1(用时20min)——GRU

速通《动手学深度学习》9.1 写在最前面九、现代循环神经网络9.1 门控循环单元&#xff08;GRU&#xff09;9.1.1. 门控隐状态9.1.1.1. 重置门和更新门9.1.1.2. 候选隐状态9.1.1.3. 隐状态 9.1.3 API简洁实现小结 &#x1f308;你好呀&#xff01;我是 是Yu欸 &#x1f30c; 20…

【状态压缩 容斥原理 组合数学】100267. 单面值组合的第 K 小金额

本文涉及知识点 状态压缩 容斥原理 组合数学 二分查找算法合集 LeetCode100267. 单面值组合的第 K 小金额 给你一个整数数组 coins 表示不同面额的硬币&#xff0c;另给你一个整数 k 。 你有无限量的每种面额的硬币。但是&#xff0c;你 不能 组合使用不同面额的硬币。 返回…

适合刚入门同学做的小程序项目

今天用uniapp做了一个酒桌数字筛子的小程序&#xff0c;因为平时玩的骰子小程序都是骰子的动画效果展示&#xff0c;喝多的时候非常容易看错&#x1f621;&#x1f601;&#xff0c;所以就想着看能不能做一个纯数字显示类型的骰盅&#xff0c;一目了然干净利落。&#x1f44f;&…

数据结构之排序了如指掌(三)

目录 题外话 正题 快速排序 Hoare法 Hoare法思路 Hoare法代码详解 挖坑法 挖坑法思路 挖坑法代码 前后指针法 前后指针法思路 前后指针法代码 小结 题外话 我们接着把没有写完的排序内容完成,快速排序其实大同小异,大家好好把思路整理一下 正题 快速排序 快速排序一…

BTS441RGATMA1 N沟道 43V 17A高侧电源开关芯片 英飞凌

BTS441RGATMA1是一款由Infineon Technologies制造的高侧开关电源芯片。 BTS441RGATMA1具有以下功能&#xff1a; 高端电源开关&#xff1a;BTS441RGATMA1是一种N通道功率场效应晶体管&#xff08;FET&#xff09;&#xff0c;用于高端电源开关应用。 高侧开关&#xff1a;该器件…

数据结构-堆详解

堆 图片&#xff1a; 二叉堆的父节点为这个子树的最值。 如何维护它。 我们发现它是一棵二叉树&#xff0c;那就自然满足若父节点为 x x x 则左儿子节点为 x 2 x\times2 x2 右儿子为 x 2 1 x\times 2 1 x21 这是显然的&#xff0c;但如果写成指针或结构体就太麻烦了&…

MacOS Docker 部署 Solr 搜索引擎

一、简介 Solr 是 Apache 下的一个顶级开源项目&#xff0c;采用 Java 开发&#xff0c;它是基于 Lucene 的全文搜索服务器。Solr 可以独立运行在 Jetty、Tomcat 等这些 Servlet 容器中。Solr 提供了比 Lucene 更为丰富的查询语言&#xff0c;同时实现了可配置、可扩展&#x…

免费使用Kimi的API接口,kimi-free-api真香

今年&#xff0c;随着各大GLM模型的开源和算力的提升&#xff0c;尤其是最近比较火热的月之暗面的Kimi 模型&#xff0c;AI应用场景中的各种智能体如雨后春笋般涌现。许多同学们纷纷表达了加入AI应用的学习和测试的愿望&#xff0c;然而各大模型提供商所提供的API的免费tokens在…

集群管理命令总结

前言 在进行TPC性能测试时用到两个集群管理命令&#xff1a;clush 和 pssh&#xff0c;这俩命令都可以在多台服务器上并发执行相同命令&#xff0c;其中个人比较推荐 clush&#xff0c;因为感觉 clush 比较好用&#xff0c;本文来总结一下 clush 和 pssh 的安装配置和使用。 …

读所罗门的密码笔记20_更好的自己

1. 民营部门 1.1. 障碍最大的一步&#xff0c;与履行协议所需要的人才和技能有关 1.2. 多样性很好&#xff0c;不要过分依赖任何一种资源&#xff0c;因为政府会出于政治原因淡化问题&#xff0c;不尊重科学&#xff0c;甚至退出协议 1.2.1. 民营部门和非政府组织的强大联盟…