Java 17 新特性之 Records(记录类)

Java 17 引入了 Records(记录类) ,这是 Java 语言中一种新的类类型,用于简化数据载体类的定义。Records 是不可变的数据类,自动提供了 ​​equals()​​​、​​hashCode()​​​、​​toString()​​ 等方法,从而减少了样板代码的编写。

这一特性最初在 Java 14 中作为预览功能引入,并在 Java 16 中成为正式特性。Java 17 继续支持并优化了这一功能。


为什么需要 Records?

在传统的 Java 开发中,当我们需要创建一个简单的数据载体类时,通常需要编写大量的样板代码,例如:

  • 构造函数
  • ​equals()​ 方法
  • ​hashCode()​ 方法
  • ​toString()​ 方法
  • Getter 方法

这些代码虽然可以通过 IDE 自动生成,但仍然会增加代码的复杂性,降低可读性。

Records 的目标是通过简化的语法,自动生成这些方法,使代码更加简洁和直观。


Records 的基本用法

定义一个 Record 类

使用 ​​record​​ 关键字定义一个记录类:

arduino 复制代码
record Person(String name, int age) {}

示例代码:

csharp 复制代码
public class Main {
    public static void main(String[] args) {
        Person person = new Person("Alice", 25);
        System.out.println(person); // 自动调用 toString()
        System.out.println("Name: " + person.name());
        System.out.println("Age: " + person.age());
    }
}

输出:

makefile 复制代码
Person[name=Alice, age=25]
Name: Alice
Age: 25

Records 的特点

  1. 自动生成构造函数
  • 编译器会自动为 Record 类生成一个构造函数,包含所有字段。
  • 你可以根据需要自定义构造函数。
arduino 复制代码
record Person(String name, int age) {
    // 自定义构造函数
    public Person {
        if (age < 0) {
            throw new IllegalArgumentException("Age cannot be negative");
        }
    }
}
  1. 自动生成访问器方法
  • 每个字段都会自动生成一个对应的访问器方法(getter),方法名与字段名相同。
  • 不需要显式地编写 ​getName()​​getAge()​
ini 复制代码
Person person = new Person("Alice", 25);
String name = person.name(); // 访问 name 字段
int age = person.age();      // 访问 age 字段
  1. 自动生成 ​equals() ​ ​hashCode() ​
  • Records 会根据字段值自动生成 ​equals()​​hashCode()​ 方法。
  • 两个 Record 对象相等的条件是它们的所有字段值都相等。
ini 复制代码
Person p1 = new Person("Alice", 25);
Person p2 = new Person("Alice", 25);
System.out.println(p1.equals(p2)); // true
  1. 自动生成 ​toString() ​
  • 编译器会自动生成 ​toString()​ 方法,格式为:​RecordName[field1=value1, field2=value2]​
ini 复制代码
Person person = new Person("Alice", 25);
System.out.println(person); // 输出:Person[name=Alice, age=25]
  1. 不可变性
  • Record 类的字段是隐式 ​final​ 的,无法修改。
  • 这使得 Record 类非常适合用作不可变数据对象。
ini 复制代码
Person person = new Person("Alice", 25);
// person.name("Bob"); // 编译错误:无法修改字段

Records 的限制

  1. 不能继承其他类
  • Record 类隐式继承自 ​java.lang.Record​,因此不能显式继承其他类。
dart 复制代码
record Person(String name, int age) extends Object {} // 编译错误
  1. 不能声明非静态字段
  • Record 类只能包含声明的组件字段,不能添加额外的实例字段。
arduino 复制代码
record Person(String name, int age) {
    private int id; // 编译错误:不能添加额外的实例字段
}
  1. 不能定义额外的构造函数
  • 只能定义紧凑构造函数(Compact Constructor)或重载构造函数。
arduino 复制代码
record Person(String name, int age) {
    public Person() { // 编译错误:不能定义无参构造函数
        this("", 0);
    }
}

Records 的高级用法

1. 局部类实现接口

Record 类可以实现接口,但不能继承其他类。

java 复制代码
interface Greeting {
    void greet();
}

record Person(String name, int age) implements Greeting {
    @Override
    public void greet() {
        System.out.println("Hello, my name is " + name);
    }
}

Person person = new Person("Alice", 25);
person.greet(); // 输出:Hello, my name is Alice

2. 嵌套 Record

可以在其他类中定义嵌套的 Record 类。

arduino 复制代码
class OuterClass {
    record Point(int x, int y) {}
}

OuterClass.Point point = new OuterClass.Point(10, 20);
System.out.println(point); // 输出:Point[x=10, y=20]

3. 泛型 Record

Record 类支持泛型。

sql 复制代码
record Pair<T, U>(T first, U second) {}

Pair<String, Integer> pair = new Pair<>("Alice", 25);
System.out.println(pair); // 输出:Pair[first=Alice, second=25]

适用场景

  1. 数据传输对象(DTO)
  • 在微服务或 API 调用中,常用于封装请求和响应数据。
  1. 不可变对象
  • 当需要创建不可变的对象时,Record 类是一个很好的选择。
  1. 简单实体类
  • 在领域驱动设计(DDD)中,可以用 Record 类表示值对象(Value Object)。
  1. 减少样板代码
  • 替代传统的 POJO 类,减少冗余代码。

总结

Records 是 Java 17 中一项非常实用的新特性,特别适合用来定义简单的数据载体类。它通过自动生成构造函数、访问器方法、​​equals()​​​、​​hashCode()​​​ 和 ​​toString()​​ 等方法,极大地简化了代码的编写,同时保证了不可变性和线程安全性。

相关推荐
bobz96541 分钟前
Python 项目打包为 Windows exe 最好用的工具是哪个?
后端
用户21411832636021 小时前
超算挑战赛实战!AI 一键生成中医药科普短视频,青少年轻松学药材
后端
还是鼠鼠1 小时前
tlias智能学习辅助系统--Maven 高级-私服介绍与资源上传下载
java·spring boot·后端·spring·maven
追逐时光者1 小时前
2025 年程序员必备 TOP 10 高效实用工具
后端
20181 小时前
Supabase migration 开发实践
后端
灵魂猎手2 小时前
3. MyBatis Executor:SQL 执行的核心引擎
java·后端·源码
Undoom2 小时前
虚拟机一站式部署Claude Code &可视化UI界面
后端
Asthenia04122 小时前
建好了表,还在手动写CRUD的xml?兄弟,真得学习MBG了!
后端
楽码2 小时前
底层技术SwissTable的实现对比
数据结构·后端·算法
m0_480502643 小时前
Rust 入门 泛型和特征-特征对象 (十四)
开发语言·后端·rust