记录类(Java 16+)
本课属于 Coddy Java 学习旅程的“面向对象编程”单元。第 51 课,共 87 课。
创建用于携带数据的简单类时,你常常要编写重复的样板代码:私有字段、构造函数、getter、toString()、equals() 和 hashCode()。Java 16 引入了记录类,以省去这些繁琐的工作。
record 是一种特殊的类,专门用于保存不可变数据。你可以使用 record 关键字,后面跟着组件列表来声明它:
record Person(String name, int age) { }
// 这一行代码会自动提供:
// -私有的 final 字段:name 和 age
// -构造方法:Person(String name, int age)
// -访问器方法:name() 和 age()
// -toString()、equals() 和 hashCode()使用记录很简单:
Person p = new Person("Alice", 30);
System.out.println(p.name()); // Alice
System.out.println(p.age()); // 30
System.out.println(p); // Person[name=Alice, age=30]请注意,访问器方法不使用 get 前缀:它们直接以字段命名。记录类会隐式声明为 final,因此不能被继承。所有字段也都是 final,因此记录类天然不可变。
你可以根据需要添加自定义方法,并重写自动生成的方法。你还可以在紧凑构造函数中添加验证:
record Person(String name, int age) {
public Person {
if (age < 0) throw new IllegalArgumentException("Age cannot be negative");
}
}记录非常适合用于 DTO、API 响应,或任何需要简单、不可变数据容器,又不想编写样板代码的场景。
挑战
简单让我们构建一个电影票预订系统,展示 Java record 的简洁之美。你将看到,record 可以省去样板代码,同时仍允许你添加自定义方法和验证逻辑。
你需要将代码分为三个文件:
Movie.java:创建一个表示电影的 record,包含三个组件:title(String)、genre(String)和durationMinutes(int)。添加一个名为getFormattedDuration()的自定义方法,以易读的格式返回时长:[hours]h [minutes]m(例如,142 分钟会变成2h 22m)。使用整数除法和取模运算计算小时数和剩余分钟数。Ticket.java:创建一个表示电影票的 record,包含三个组件:movie(Movie)、seatNumber(String)和price(double)。添加一个紧凑构造函数来验证票价,如果票价小于或等于零,就抛出带有消息Price must be positive的IllegalArgumentException。再添加一个名为printTicket()的自定义方法,返回一个多行字符串:========== TICKET ========== Movie: [movie title] Genre: [movie genre] Duration: [formatted duration from movie] Seat: [seatNumber] Price: $[price] ============================Main.java:将预订系统组合起来!你会收到五个输入:电影标题(String)、类型(String)、时长(分钟,int)、座位号(String)和票价(double)。使用前三个输入创建一个 Movie record,然后使用电影、座位号和票价创建一个 Ticket record。打印对 ticket 调用
printTicket()的结果。
你会依次收到五个输入:电影标题、类型、时长(分钟)、座位号和票价。
注意,与传统类相比,record 简洁了许多:不需要编写构造函数、getter、toString()、equals() 或 hashCode()。紧凑构造函数让你无需重复赋值字段就能添加验证逻辑,而且你仍然可以按需添加自定义方法!
亲手试试
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 读取输入
String title = scanner.nextLine();
String genre = scanner.nextLine();
int durationMinutes = Integer.parseInt(scanner.nextLine());
String seatNumber = scanner.nextLine();
double price = Double.parseDouble(scanner.nextLine());
// TODO:使用 title、genre 和 durationMinutes 创建 Movie 记录
// TODO:使用电影、seatNumber 和 price 创建 Ticket 记录
// TODO:使用 printTicket() 方法打印票据
}
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Java 在线编译器