06、记录类(Record)

  • 记录 ( record) :是一种特殊形式的类,其状态 不可变,而且公共可读
    • 在 Java 语言规范中,一个 记录(Record) 实例字段 称为 组件 (component)
    • 记录(Record) 不能被继承
    • 记录(Record) 的 实例变量,默认是有 final 修饰
  • Java 16 中引入的 记录(Record) 是一种新的类型,旨在简化 不可变数据模型声明使用

一、记录 vs 普通类


1、代码对比


  • Record 类定义:
package org.rainlotus.materials.javabase.a04_oop.aboutrecord;

import java.math.BigDecimal;

// 自动生成 全参构造、访问器方法、equals、hashCode、toString
public record Product(String id, String name, BigDecimal price) {
}

class Test{
    public static void main(String[] args) {
        var p = new Product("1234", "张三", new BigDecimal("12345.12"));

        // 1234	    张三		12345.12
        System.out.println(p.id() + "\t\t" + p.name() + "\t\t" + p.price());
    }
}
  • 用普通类模拟记录类:
// 需手动生成 全参构造、访问器方法、equals、hashCode、toString
public class Product {
    private final String id;
    private final String name;
    private final BigDecimal price;

    public Product(String id, String name, BigDecimal price) {
        this.id = id;
        this.name = name;
        this.price = price;
    }

    // 手动生成 getter/equals/hashCode/toString 等方法
    public String id(){
        return id;
    }

    public String name(){
        return name;
    }

    public BigDecimal price(){
        return price;
    }
}

class Test{
    public static void main(String[] args) {
        var p = new Product("1234", "张三", new BigDecimal("12345.12"));

        // 1234	    张三		12345.12
        System.out.println(p.id() + "\t\t" + p.name() + "\t\t" + p.price());
    }
}

2、小结


特性记录(Record)普通类(Class)
不可变性所有字段隐式 final需手动声明 final 字段
样板代码自动生成方法(equals, hashCode等)需手动实现或依赖 IDE 生成
继承不能继承其他类,但可实现接口可继承其他类并实现接口
构造方法自动生成全参构造方法需显式定义构造方法
应用场景不可变数据载体(DTO、值对象)通用业务逻辑、可变状态对象

二、记录(Record)的核心特性


1、不可变性(Immutability)

  • 记录的所有字段(称为 组件)默认是 final 的,对象一旦创建后,其状态不可修改
  • 编译器自动生成基于所有组件构造函数、访问器方法 等。
// 作为方法返回值(不可变)
public record Response<T>(boolean success, T data) { }

Response<String> response = new Response<>(true, "操作成功");

// 需要可变状态的业务对象
public class ShoppingCart {
    private List<Product> items = new ArrayList<>();

    public void addItem(Product item) {
        items.add(item);
    }

    public void removeItem(Product item) {
        items.remove(item);
    }
}

2、自动生成的方法

  • 构造方法:根据组件生成全参构造方法。
  • 访问器方法:为每个组件生成 public 访问器(如 name() 而非传统 getName())。
  • equals() hashCode():基于所有组件进行值比较。
  • toString():返回包含所有组件名称和值的字符串。

3、限制

  • 不能显式继承其他类(但可以实现接口)。
  • 记录类隐式 final 的,不可被继承
  • 组件必须是不可变字段(隐式 final)。

4、自定义行为

  • 允许在记录中添加静态方法、实例方法、构造函数验证、类变量 等:
public record Person(String name, int age) {
    // 自定义构造函数验证
    public Person {
        if (age < 0) throw new IllegalArgumentException("年龄不能为负数");
    }
    
    // 添加实例方法
    public String greet() {
        return "Hello, " + name;
    }
}

  • 注意:不能手动添加 实例变量

三、应用场景


1、数据传输对象(DTO)

  • 用于在不同层(如数据库、服务层、前端)之间传输数据。
  • 替代传统的 POJO,减少样板代码。
// 替代传统DTO类
public record UserDTO(String username, String email, LocalDateTime createdAt) { }

2、值对象(Value Objects)

  • 表示简单的不可变数据聚合,如坐标、金额、日期范围等。
// 表示二维坐标
public record Coordinate(double latitude, double longitude) { }

// 表示金额(含货币单位)
public record Money(BigDecimal amount, Currency currency) { }

3、模式匹配(Pattern Matching)

  • 结合 <font style="color:#000000;">instanceof</font><font style="color:#000000;">switch</font> 表达式,简化数据解构。
Object obj = new Point(3, 4);
if (obj instanceof Point(int x, int y)) {
    System.out.println("坐标: (" + x + ", " + y + ")");
}

4、临时数据容器

  • 在流式操作(Stream API)中作为中间结果的载体。
List<Person> people = ...;
List<String> names = people.stream()
    .map(p -> new NameRecord(p.firstName(), p.lastName()))
    .filter(n -> n.lastName().startsWith("A"))
    .map(n -> n.firstName() + " " + n.lastName())
    .toList();

四、进阶用法


1、实现接口

  • 记录可以实现接口扩展行为
public interface Shape {
    double area();
}

public record Circle(double radius) implements Shape {
    @Override
    public double area() {
        return Math.PI * radius * radius;
    }
}

2、静态工厂方法

  • 提供更灵活的构造方式
public record Email(String value) {
    public static Email of(String input) {
        if (!input.contains("@")) throw new IllegalArgumentException("Invalid email");
        return new Email(input);
    }
}

// 使用工厂方法创建
Email email = Email.of("user@example.com");

3、序列化支持

  • 记录的序列化行为与普通类一致,但需注意不可变性:
public record User(String id, String name) implements Serializable { }

// 序列化与反序列化
User user = new User("123", "Alice");
// ... 序列化操作
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值