0Pricing
Java Academy · 课时

认识记录类

将记录类声明为简洁的不可变数据载体,并理解其自动生成的成员

认识记录类 是 CoddyKit 上的免费 Java Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Java Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Java Academy 课程共包含 4 节课。

认识记录类

Java 记录类(Java 16+)是一种简洁的不可变数据载体类声明方式。它会自动生成样板代码,包括构造函数、访问器、equals、hashCode 和 toString。

声明记录类

使用 record 关键字,后面跟记录类名称和组件列表。每个组件都会成为一个私有的不可重新赋值字段,并生成一个公共访问器方法。

record Point(double x, double y) {}

Point p = new Point(3.0, 4.0);
System.out.println(p.x());      // 3.0 (accessor, not getX())
System.out.println(p.y());      // 4.0
System.out.println(p);          // Point[x=3.0, y=4.0]
System.out.println(p.equals(new Point(3.0, 4.0))); // true

自动生成的成员

编译器会为每个记录类自动生成:规范构造函数、公共访问器、equals()、hashCode() 和 toString()。您无需手动编写这些内容。

record Product(String name, double price, int stock) {}

Product p1 = new Product("Widget", 9.99, 100);
Product p2 = new Product("Widget", 9.99, 100);

System.out.println(p1.name());          // Widget
System.out.println(p1.price());         // 9.99
System.out.println(p1.equals(p2));      // true (structural)
System.out.println(p1.hashCode() == p2.hashCode()); // true
System.out.println(p1);                 // Product[name=Widget, price=9.99, stock=100]

记录类是不可变的

记录类的组件是 final 的。构造完成后,您无法修改它们——记录类用于表示不可变值对象。

record Money(long cents, String currency) {}

Money price = new Money(999, "USD");
// price.cents = 500; // Compile error — final field!

// To "update" a record, create a new one
Money discounted = new Money(price.cents() - 100, price.currency());
System.out.println(discounted); // Money[cents=899, currency=USD]

记录类只能继承 Object

记录类会隐式继承 java.lang.Record,不能继承其他类,但可以实现接口。

interface Describable { String describe(); }

record Circle(double radius) implements Describable {
    public String describe() {
        return String.format("Circle with radius %.1f", radius);
    }

    public double area() {
        return Math.PI * radius * radius;
    }
}

Circle c = new Circle(5.0);
System.out.println(c.describe()); // Circle with radius 5.0
System.out.printf("Area: %.2f%n", c.area()); // Area: 78.54

集合中的记录类

由于记录类会根据所有组件正确实现 equals 和 hashCode,因此可以正确地用作映射键和集合元素。

import java.util.*;

record Coordinate(int row, int col) {}

Map<Coordinate, String> grid = new HashMap<>();
grid.put(new Coordinate(0, 0), "Origin");
grid.put(new Coordinate(1, 2), "Target");

// Lookup with equal-valued record works correctly
System.out.println(grid.get(new Coordinate(0, 0))); // Origin
System.out.println(grid.get(new Coordinate(1, 2))); // Target

Set<Coordinate> visited = new HashSet<>();
visited.add(new Coordinate(3, 3));
System.out.println(visited.contains(new Coordinate(3, 3))); // true

作为 DTO 的记录类

记录类非常适合用于 REST API 中的数据传输对象(DTO)——它们可以在各层之间传递数据,而不包含行为。

record CreateUserRequest(String email, String displayName, String plan) {}

record UserResponse(long id, String email, String displayName,
                    String plan, String createdAt) {}

// Simulating a service call
static UserResponse createUser(CreateUserRequest req) {
    long id = 42L;
    return new UserResponse(id, req.email(), req.displayName(),
        req.plan(), java.time.Instant.now().toString());
}

CreateUserRequest req = new CreateUserRequest("alice@example.com", "Alice", "PRO");
UserResponse resp = createUser(req);
System.out.println(resp);

解构记录类

记录类非常适合与模式匹配结合使用。您可以在 switch 表达式中解构记录类(Java 21+)。

sealed interface Shape permits Circle, Rectangle, Triangle {}
record Circle(double radius) implements Shape {}
record Rectangle(double width, double height) implements Shape {}
record Triangle(double base, double height) implements Shape {}

static double area(Shape s) {
    return switch (s) {
        case Circle(double r)            -> Math.PI * r * r;
        case Rectangle(double w, double h) -> w * h;
        case Triangle(double b, double h) -> 0.5 * b * h;
    };
}

System.out.printf("%.2f%n", area(new Circle(5)));         // 78.54
System.out.printf("%.2f%n", area(new Rectangle(4, 6)));   // 24.00

记录类的序列化

记录类声明为实现 Serializable 后,会自然地支持序列化。它们开箱即用地适用于 JSON 库(Jackson、Gson)。

// With Jackson (add @JsonProperty if needed)
import com.fasterxml.jackson.databind.ObjectMapper;

record OrderSummary(String orderId, double total, String status) {}

ObjectMapper mapper = new ObjectMapper();
OrderSummary order = new OrderSummary("ORD-001", 149.99, "SHIPPED");

String json = mapper.writeValueAsString(order);
System.out.println(json);
// {"orderId":"ORD-001","total":149.99,"status":"SHIPPED"}

OrderSummary restored = mapper.readValue(json, OrderSummary.class);
System.out.println(order.equals(restored)); // true

嵌套记录类

记录类可以将其他记录类作为组件,从而构建丰富的不可变对象图。

record Address(String street, String city, String country) {}
record Customer(long id, String name, Address address) {}

Address addr = new Address("123 Main St", "New York", "US");
Customer customer = new Customer(1L, "Alice", addr);

System.out.println(customer.name());              // Alice
System.out.println(customer.address().city());   // New York
System.out.println(customer);                    // Customer[id=1, name=Alice, address=Address[street=123 Main St, city=New York, country=US]]

记录类的限制

记录类有一些需要注意的限制:

  • 不能继承其他类(会隐式继承 Record)
  • 组件始终不可重新赋值——不能包含可变状态
  • 不能在组件列表之外声明实例字段
  • 不能声明为抽象类
// Records CAN have static fields and methods
record Temperature(double celsius) {
    static final double ABSOLUTE_ZERO = -273.15;

    public double toFahrenheit() {
        return celsius * 9.0/5.0 + 32;
    }

    public static Temperature fromFahrenheit(double f) {
        return new Temperature((f - 32) * 5.0/9.0);
    }
}
System.out.println(Temperature.fromFahrenheit(98.6)); // Temperature[celsius=37.0]

快速检查

Java 编译器会为记录类自动生成哪些成员?

回顾:认识记录类

要点:

  • 记录类只需极少的样板代码即可声明不可变数据载体
  • 自动生成:规范构造函数、访问器、equals、hashCode 和 toString
  • 组件不可重新赋值——记录类在设计上是不可变的
  • 记录类可以实现接口,但不能继承类
  • 非常适合数据传输对象、值对象和 API 响应
  • 由于采用结构相等性,可以正确地用作 HashMap 的键和 HashSet 的元素

常见问题解答

「认识记录类」课时是免费的吗?

是的 — 「认识记录类」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Java Academy 课程的其余内容,请升级到 CoddyKit PRO。 Java Academy 课程共包含 4 节课。

「认识记录类」这节课中我会学到什么?

将记录类声明为简洁的不可变数据载体,并理解其自动生成的成员 你通过在浏览器中直接运行的动手代码来练习 Java Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Java Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Java Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「认识记录类」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Java Academy 课中编写并运行代码吗?

能。每节 Java Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 认识记录类
  2. 紧凑构造方法与验证
  3. 为记录类添加自定义方法
  4. 记录类、类与 Lombok 的比较
← 返回 Java Academy