云计算百科
云计算领域专业知识百科平台

Java Record使用指南

Java Record使用指南

  • Java Record 使用指南
    • 一、Record 的核心优势
      • 1. 代码简洁性
      • 2. 不可变性保证
      • 3. 自动生成样板代码
      • 4. 与密封接口完美配合
    • 二、什么时候使用 Record
      • ✅ 适合场景
        • 1. DTO(数据传输对象)
        • 2. VO(值对象)
        • 3. 配置对象
        • 4. 集合操作的返回值
        • 5. JSON-RPC 消息
        • 6. 事件对象
        • 7. 数据库查询结果
      • ❌ 不适合场景
        • 1. 需要可变状态的实体
        • 2. 需要继承的场景
        • 3. 需要延迟初始化或复杂构造逻辑
        • 4. 需要 setter 方法
    • 三、Record 的高级用法
      • 1. 添加参数校验
      • 2. 添加自定义方法
      • 3. 添加静态工厂方法
      • 4. 实现接口
      • 5. 嵌套 Record
    • 四、Record 与 Lombok 对比
      • 建议
    • 五、最佳实践
      • ✅ 推荐
      • ❌ 避免
    • 六、总结
      • 使用 Record 的时机
      • 不使用 Record 的时机

Java Record 使用指南

一、Record 的核心优势

1. 代码简洁性

// 传统 class:50+ 行
public class User {
private final String name;
private final int age;
// + 构造函数 + getter + equals + hashCode + toString
}

// Record:1 行
public record User(String name, int age) {}

2. 不可变性保证

  • 所有字段自动声明为 private final
  • 创建后无法修改,天然线程安全
  • 适合并发编程场景

3. 自动生成样板代码

  • 私有 final 字段
  • 全参构造函数
  • 访问器方法(name() 而非 getName())
  • equals()、hashCode()、toString()

4. 与密封接口完美配合

public sealed interface Message permits Request, Response {}
public record Request(String method, Object params) implements Message {}
public record Response(Object result) implements Message {}

二、什么时候使用 Record

✅ 适合场景

1. DTO(数据传输对象)

public record UserDTO(String name, String email, Integer age) {}

2. VO(值对象)

public record Money(BigDecimal amount, String currency) {}
public record DateRange(LocalDate start, LocalDate end) {}

3. 配置对象

public record DatabaseConfig(String url, String username, String password) {}

4. 集合操作的返回值

public record PageResult<T>(List<T> data, long total, int page) {}

// 使用
PageResult<User> result = userService.getPage(1, 10);
System.out.println("总数:" + result.total());

5. JSON-RPC 消息

public record JSONRPCRequest(String jsonrpc, String method, Object id, Object params) {}
public record JSONRPCResponse(String jsonrpc, Object id, Object result, JSONRPCError error) {}

6. 事件对象

public record UserCreatedEvent(String userId, String email, Instant timestamp) {}

7. 数据库查询结果

public record UserSummary(String name, long orderCount, BigDecimal totalAmount) {}

❌ 不适合场景

1. 需要可变状态的实体

// ❌ 不适合:实体需要修改状态
public record UserEntity(String name, int age) {}
UserEntity user = new UserEntity("张三", 25);
// user.setName("李四"); // 编译错误!

// ✅ 应该使用传统 class 或 Lombok
@Data
public class UserEntity {
private String name;
private int age;
}

2. 需要继承的场景

// ❌ Record 不能继承其他类
public record AdminUser(String name, String role) extends User {} // 编译错误!

// ✅ 使用传统 class
public class AdminUser extends User {
private String role;
}

3. 需要延迟初始化或复杂构造逻辑

// ❌ Record 的构造函数必须初始化所有字段
public record ComplexObject(LazyField field) {
// 无法实现延迟初始化
}

// ✅ 使用传统 class
public class ComplexObject {
private LazyField field;

public LazyField getField() {
if (field == null) {
field = new LazyField(); // 延迟初始化
}
return field;
}
}

4. 需要 setter 方法

// ❌ Record 没有 setter
public record Config(String value) {}
Config config = new Config("old");
// config.setValue("new"); // 编译错误!

// ✅ 使用传统 class 或 Lombok
@Data
public class Config {
private String value;
}

三、Record 的高级用法

1. 添加参数校验

public record Email(String value) {
// 紧凑构造函数
public Email {
if (!value.contains("@")) {
throw new IllegalArgumentException("无效的邮箱地址");
}
}
}

2. 添加自定义方法

public record DateRange(LocalDate start, LocalDate end) {
public boolean contains(LocalDate date) {
return !date.isBefore(start) && !date.isAfter(end);
}

public long days() {
return ChronoUnit.DAYS.between(start, end);
}
}

3. 添加静态工厂方法

public record Money(BigDecimal amount, String currency) {
public static Money of(double amount, String currency) {
return new Money(BigDecimal.valueOf(amount), currency);
}

public static Money CNY(double amount) {
return of(amount, "CNY");
}
}

// 使用
Money money = Money.CNY(100.00);

4. 实现接口

public interface Comparable<T> {
int compareTo(T o);
}

public record Student(String name, int score) implements Comparable<Student> {
@Override
public int compareTo(Student other) {
return Integer.compare(this.score, other.score);
}
}

5. 嵌套 Record

public record Order(
String orderId,
List<OrderItem> items,
Address shippingAddress
) {
public record OrderItem(String productId, int quantity, BigDecimal price) {}
public record Address(String city, String street, String zipCode) {}
}

四、Record 与 Lombok 对比

特性RecordLombok @Value
语言支持 原生 Java 16+ 需要 Lombok 依赖
IDE 支持 原生支持 需要安装插件
编译速度 更快 稍慢(注解处理)
不可变性 ✅ 强制 ✅ 强制
可变性支持 ❌ 不支持 ⚠️ 不推荐
继承 ❌ 不能继承类 ✅ 可以继承
构造函数 只能全参 支持多种
Builder 模式 需手写 ✅ @Builder

建议

  • Java 16+ 项目:优先使用 Record
  • 需要灵活性:使用 Lombok
  • 简单数据载体:Record
  • 复杂业务对象:Lombok 或传统 class

五、最佳实践

✅ 推荐

  • 命名规范

    // ✅ 使用名词命名
    public record UserDTO(...) {}
    public record OrderSummary(...) {}

    // ❌ 避免动词
    public record getUser(...) {}

  • 保持简洁

    // ✅ 字段少而精
    public record Point(int x, int y) {}

    // ❌ 字段过多(考虑拆分)
    public record User(long f1, long f2, ..., long f20) {}

  • 添加必要的校验

    public record Age(int value) {
    public Age {
    if (value < 0 || value > 150) {
    throw new IllegalArgumentException("年龄不合法");
    }
    }
    }

  • 配合密封接口使用

    public sealed interface Result<T>
    permits Success, Failure {
    T getOrNull();
    }

    public record Success<T>(T value) implements Result<T> {
    @Override
    public T getOrNull() { return value; }
    }

    public record Failure<T>(String error) implements Result<T> {
    @Override
    public T getOrNull() { return null; }
    }

  • ❌ 避免

  • 不要在 Record 中存储大量数据

    // ❌ 不适合
    public record LargeData(byte[] data1, byte[] data2, ...) {}

    // ✅ 考虑使用传统 class 或流式处理

  • 不要在 Record 中存储可变对象引用

    // ❌ 虽然 Record 不可变,但引用的对象可变
    public record Config(List<String> items) {}
    Config config = new Config(new ArrayList<>());
    config.items().add("hack"); // 破坏了不可变性!

    // ✅ 使用不可变集合
    public record Config(List<String> items) {
    public Config {
    items = List.copyOf(items); // 防御性拷贝
    }
    }

  • 六、总结

    使用 Record 的时机

    ✅ 纯数据载体(DTO、VO、配置) ✅ 需要不可变性 ✅ 不需要继承 ✅ 字段数量适中 ✅ 配合密封接口使用

    不使用 Record 的时机

    ❌ 需要可变状态 ❌ 需要继承其他类 ❌ 需要延迟初始化 ❌ 需要 setter 方法 ❌ 字段过多(> 10 个)

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » Java Record使用指南
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!