Java 16 中引入的 record的基本用法
在 Java 16 中引入的 record
是一种特殊的类,主要用于创建不可变的数据载体类。它可以大大简化代码,自动生成许多常用方法,让开发者更专注于数据本身而非样板代码。
一、record 的基本定义
record
的定义格式非常简洁,使用 record
关键字声明,后跟类名和括号内的成员变量列表:
// 定义一个简单的 record
record Point(int x, int y) {}
这个简单的定义等价于一个包含 x
和 y
两个私有 final 字段、构造方法、equals()
、hashCode()
和 toString()
方法的类。
二、自动生成的成员
定义一个 record
后,编译器会自动生成以下内容:
- 与声明的参数同名的私有 final 字段
- 全参构造方法
- 每个字段的 getter 方法(注意:方法名与字段名相同,没有
get
前缀) - 重写的
equals()
方法(比较所有字段) - 重写的
hashCode()
方法(基于所有字段计算) - 重写的
toString()
方法(包含所有字段的名称和值)
示例使用:
public class RecordDemo {public static void main(String[] args) {Point p1 = new Point(10, 20);Point p2 = new Point(10, 20);// 调用自动生成的 getter 方法(注意没有 get 前缀)System.out.println("x: " + p1.x());System.out.println("y: " + p1.y());// 调用自动生成的 toString()System.out.println(p1); // 输出:Point[x=10, y=20]// 调用自动生成的 equals()System.out.println(p1.equals(p2)); // 输出:true// 调用自动生成的 hashCode()System.out.println(p1.hashCode());System.out.println(p2.hashCode());}
}
三、record 的特性和限制
-
不可变性:
- 所有字段都是
final
的,无法在创建后修改 - 不能添加非 final 的字段
- 所有字段都是
-
继承关系:
- 隐式继承
java.lang.Record
类,不能显式继承其他类 - 可以实现接口
- 隐式继承
-
成员声明:
- 可以声明静态字段、静态方法
- 可以声明实例方法
- 不能声明实例字段(除了定义中声明的字段)
-
构造方法:
- 可以声明紧凑构造方法(无参数列表)来验证参数
- 不能声明无参构造方法(除非所有字段都有默认值,但语法不支持)
紧凑构造方法示例:
record PositivePoint(int x, int y) {// 紧凑构造方法,用于参数验证PositivePoint {if (x < 0 || y < 0) {throw new IllegalArgumentException("坐标不能为负数");}}
}
四、适用场景
record
特别适合以下场景:
- 数据传输对象(DTOs)
- 简单的值对象(如坐标、日期范围等)
- 临时数据容器(如流处理中的中间结果)
- 枚举 - like 结构但需要更多灵活性
五、应用举例
1792. 最大平均通过率(力扣题目)
一所学校里有一些班级,每个班级里有一些学生,现在每个班都会进行一场期末考试。给你一个二维数组 classes
,其中 classes[i] = [passi, totali]
,表示你提前知道了第 i
个班级总共有 totali
个学生,其中只有 passi
个学生可以通过考试。
给你一个整数 extraStudents
,表示额外有 extraStudents
个聪明的学生,他们 一定 能通过任何班级的期末考。你需要给这 extraStudents
个学生每人都安排一个班级,使得 所有 班级的 平均 通过率 最大 。
一个班级的 通过率 等于这个班级通过考试的学生人数除以这个班级的总人数。平均通过率 是所有班级的通过率之和除以班级数目。
请你返回在安排这 extraStudents
个学生去对应班级后的 最大 平均通过率。与标准答案误差范围在 10-5
以内的结果都会视为正确结果。
示例 1:
输入:classes = [[1,2],[3,5],[2,2]], extraStudents
= 2
输出:0.78333
解释:你可以将额外的两个学生都安排到第一个班级,平均通过率为 (3/4 + 3/5 + 2/2) / 3 = 0.78333。
示例 2:
输入:classes = [[2,4],[3,9],[4,5],[2,10]], extraStudents
= 4
输出:0.53485
解法:
class Solution {public double maxAverageRatio(int[][] classes, int extraStudents) {record Node(double gain, int a, int b) {}PriorityQueue<Node> pq = new PriorityQueue<>((a, b) -> Double.compare(b.gain, a.gain));for (int[] c : classes) {int a = c[0];int b = c[1];double gain = 1.0 * (b - a) / (1L * b * (b + 1));pq.add(new Node(gain, a, b));}while (extraStudents-- > 0) {Node top = pq.poll();int a = top.a + 1;int b = top.b + 1;double gain = 1.0 * (b - a) / (1L * b * (b + 1));pq.add(new Node(gain, a, b));}double sum = 0;int n = pq.size();while (!pq.isEmpty()) {Node top = pq.poll();sum += 1.0 * top.a / top.b;}return sum / n;}
}