当前位置: 首页 > news >正文

学习笔记-Record类

 359:Records (Preview)
384:Records (Second Preview)
395:

Records

405:Record Patterns (Preview)
432:Record Patterns (Second Preview)
440:Record Patterns

Record类由 JEP 359 于 2019 年年中提出,并于 2020 年初在 JDK 14 中作为预览特性交付。

前面三个JEP是Record类的产生后面三个PEP是Record类的功能扩展。

Record类的产生

背景

人们常常抱怨"Java 过于冗长"或"仪式感太强"。其中最糟糕的例子是一些仅用于承载少量值的不可变数据类。正确编写一个数据承载类涉及大量低价值、重复且易出错的代码:构造函数、访问器、 equals、 hashCode、 toString等方法。

Record类是Java语言中的一种新类。记录的目的是声明一小组变量应被视为一种新的实体。记录声明其状态——变量组——并承诺匹配该状态的 API。这意味着记录放弃了一个类通常享受的自由——即类 API 与其内部表示解耦的能力——但作为回报,记录变得更加简洁。

Record类代码示例

record Point(int x, int y) { }

等于

import java.util.Objects;final class Point {private final int x;private final int y;Point(int x, int y) { this.x = x;this.y = y;}int x() { return x; }int y() { return y; }public boolean equals(Object o) { if (!(o instanceof Point)) return false;Point other = (Point) o;return other.x == x && other.y == y;}public int hashCode() {return Objects.hash(x, y);}public String toString() { return String.format("Point[x=%d, y=%d]", x, y);}
}

Record类的特性

与枚举一样,记录也是类的受限形式。它非常适合作为“数据载体”,即包含不想更改的数据的类,以及只包含最基本的方法(如构造函数和访问器)的类。

记录类的超类总是 java.lang.Record 类似于枚举类的超类总是java.lang.Enum但记录类不能显式地扩展任何类,甚至不能扩展其隐式超类 Record 

Record类成员属性都要写在后面括号里

Record类成员属性默认被final修饰,并且不能通过反射修改

Record类成员属性默认有一个public的属性访问方法,没有set方法。

有且仅有一个公共构造函数,构造函数包含了该Record类所有成员属性

有默认的equals、 hashCode、 toString方法

记录类的成员属性可以是密封类,记录类可以实现密封口

Record类和密封类型

public sealed interface Exprpermits ConstantExpr, PlusExpr, TimesExpr, NegExpr {///public  void ff();
}record ConstantExpr(int i)       implements Expr {@Overridepublic void ff() {System.out.printf("Constant %d\n", i);}
}
record PlusExpr(Expr a, Expr b)  implements Expr {@Overridepublic void ff() {System.out.printf("Constant %d\n", a,b);}
}
record TimesExpr(Expr a, Expr b) implements Expr {@Overridepublic void ff() {System.out.printf("Constant %d\n", a,b);}
}
record NegExpr(Expr e)           implements Expr {@Overridepublic void ff() {System.out.printf("Constant %d\n", e);}
}

记录类的成员属性可以是密封类,记录类可以实现密封接口。

记录与密封类型(JEP 360)配合得很好。记录和密封类型的组合有时被称为代数数据类型。记录使我们能够表达产品类型,而密封类型使我们能够表达和类型。

Record类的注解

记录组件上的字段有注解,那么该注解出现在相应的字段上和访问器方法上

record Point(@MyAnno("value")int x, int y) {
}

等于

final class Point {@MyAnno("value")private final int x;@MyAnno("value")int x() { return x; }//其他不变...
}

如果注解只想出现在对应的字段或者访问方法

可以对注解进行@Target注解修饰

@Target({ElementType.FIELD,ElementType.TYPE,ElementType.RECORD_COMPONENT})
public @interface MyAnno {String value();
}

Record类的反射

java.lang.Class添加以下公共方法:

RecordComponent[] getRecordComponents()方法 getRecordComponents()返回一个 java.lang.reflect.RecordComponent对象的数组。该数组中的元素对应于记录的组件,顺序与它们在记录声明中出现的顺序相同。可以从数组中的每个元素中提取更多信息,包括其名称、注解和访问器方法。
boolean isRecord()方法isRecord如果给定的类被声明为记录,则返回 true。(与isEnum相比。)

        Class c =Class.forName("Point");if(c.isRecord()){RecordComponent[] recordComponents = c.getRecordComponents();Arrays.stream(recordComponents).forEach(System.out::println);}Method[] methods = c.getMethods();Arrays.stream(methods).forEach(System.out::println);

Record类的功能扩展

在 JDK 16 中,JEP 394 扩展了 instanceof运算符以接受类型模式并执行模式匹配

在 JDK 17、JDK 18 和 JDK 19 中,我们通过 JEP 406、JEP 420 和 JEP 427,将类型模式的使用扩展到了switch案例标签

增强型for语句头部的支持

instanceof

例1
    static void printSum(Object o) {if (o instanceof Point p) {int x = p.x();int y = p.y();System.out.println(x+y);}}

可以简写成

    static void printSum(Object o) {if (o instanceof Point(int x, int y)) {System.out.println(x+y);}}
例2
    enum Color { RED, GREEN, BLUE }record ColoredPoint(Point p, Color c) {}record Rectangle(ColoredPoint upperLeft, ColoredPoint lowerRight) {}static void printUpperLeftColoredPoint(Rectangle r) {if (r instanceof Rectangle(ColoredPoint ul, ColoredPoint lr)) {System.out.println(ul.c());}}

可以简写成

    static void printColorOfUpperLeftPoint(Rectangle r) {if (r instanceof Rectangle(ColoredPoint(Point p, Color c),ColoredPoint lr)) {System.out.println(c);}}

switch

配合Switch必须让case详尽,或者加上default分支,都则报错

增强型for(第二次预览提出,正式上线删除)

该功能可能在未来的 JEP 中重新提出

增强1

循环中可以命名成员变量以便使用

        Point point = new Point(1, 4);List<Point> points = new ArrayList<>();points.add(point);for (Point(var x, var y) : points) { }
增强2

如果 R 是一个记录模式,那么形式为

for (R : e) S

等效于

for (var tmp : e) {switch(tmp) {case null -> throw new MatchException(new NullPointerException());case R -> S;}
}

Java21发布版中只能用普通模式

     Point point = new Point(1, 4);List<Point> points = new ArrayList<>();points.add(point);for (Point p : points) { }

http://www.xdnf.cn/news/1392517.html

相关文章:

  • 忆联参与制定消费级SSD团体标准正式出版! 以“高可靠”引领行业提质增效与用户体验升级
  • 联想打印机2268w安装
  • Ubuntu22.04系统安装Opencv,无法定位包libjasper-dev libdc1394-22-dev的解决办法
  • 微信小程序调用蓝牙打印机教程(TSPL命令)
  • 死锁检测 及其测试用例
  • 地铁隧道病害智能巡检系统——机器视觉技术的深度应用
  • Idea2025.2 MybatisX插件失效问题
  • vue3+wangEditor实现富文本编辑器
  • cursor的setting設置換行
  • 命令拓展(草稿)
  • Vue开发准备
  • Silvaco TCAD | Victory DoE的基本使用方法(三)
  • nacos单机部署并开启鉴权
  • 2025.8.29机械臂实战项目
  • Windows 下 MSYS2 + MinGW-w64 配置 Fyne GUI 编译环境全流程
  • Redis-分布式缓存
  • Java深拷贝与浅拷贝核心解析
  • 设计模式:装饰模式(Decorator Pattern)
  • Kubernetes 与 GitOps 的深度融合实践指南
  • 【3D入门-指标篇上】3D 网格重建评估指标详解与通俗比喻
  • 3D 数字孪生可视化技术在学校项目中的应用
  • “破译”的密钥/算法类型
  • 【工具】开源大屏设计器 自用整理
  • LeetCode第二题知识点2 ---- 栈、堆、地址
  • LeetCode - 128. 最长连续序列
  • Vue3+Ant-design-vue 实现树形穿梭框
  • BlueKing-ci
  • 币安创始人赵长鹏:香港需要更广泛的加密货币产品来与美国和阿联酋竞争
  • docker-相关笔记
  • Cesium 入门教程(十三):粒子系统实例