java Records 怎么使用

Java Records 是 Java 14 引入、Java 16 正式化的特性,用于创建不可变的数据载体类。下面详细说明使用方法:

1. 基本语法

java 复制代码
public record Point(int x, int y) {}

编译器会自动生成:

  • 私有 final 字段(x, y
  • 规范构造函数
  • 访问器方法(x(), y()
  • equals(), hashCode(), toString()

2. 自定义构造函数

紧凑构造函数(推荐)

java 复制代码
public record Point(int x, int y) {
    public Point {
        // 参数验证
        if (x < 0 || y < 0) {
            throw new IllegalArgumentException("坐标不能为负数");
        }
        // 无需显式赋值,编译器自动处理
    }
}

传统构造函数

java 复制代码
public record Point(int x, int y) {
    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

3. 添加方法

java 复制代码
public record Point(int x, int y) {
    // 实例方法
    public double distanceTo(Point other) {
        int dx = x - other.x;
        int dy = y - other.y;
        return Math.sqrt(dx * dx + dy * dy);
    }
    
    // 静态方法
    public static Point origin() {
        return new Point(0, 0);
    }
}

4. 实际使用示例

java 复制代码
// 定义Record
public record User(
    Long id,
    String username,
    String email,
    LocalDateTime createdAt
) {
    public User {
        // 验证逻辑
        Objects.requireNonNull(username);
        Objects.requireNonNull(email);
        
        // 数据转换
        email = email.toLowerCase();
    }
    
    // 便捷构造函数
    public User(String username, String email) {
        this(null, username, email, LocalDateTime.now());
    }
}

// 使用
public class Main {
    public static void main(String[] args) {
        // 创建实例
        User user = new User(1L, "alice", "ALICE@EXAMPLE.COM", LocalDateTime.now());
        
        // 访问器方法(没有get前缀)
        System.out.println(user.username()); // "alice"
        System.out.println(user.email());    // "alice@example.com"
        
        // 自动生成的toString()
        System.out.println(user); 
        // 输出: User[id=1, username=alice, email=alice@example.com, ...]
        
        // 解构(Java 21+)
        if (user instanceof User(Long id, String name, String email, LocalDateTime time)) {
            System.out.println("ID: " + id);
        }
    }
}

5. 结合其他特性

与 Stream API 结合

java 复制代码
record Person(String name, int age) {}

List<Person> people = List.of(
    new Person("Alice", 25),
    new Person("Bob", 30)
);

// 过滤并获取名字
List<String> names = people.stream()
    .filter(p -> p.age() > 25)
    .map(Person::name)
    .toList();

作为 DTO 使用

java 复制代码
// API 响应
public record ApiResponse<T>(
    boolean success,
    String message,
    T data,
    LocalDateTime timestamp
) {}

// 在Spring Boot中作为返回类型
@RestController
public class UserController {
    @GetMapping("/users/{id}")
    public ApiResponse<User> getUser(@PathVariable Long id) {
        User user = userService.findById(id);
        return new ApiResponse<>(true, "成功", user, LocalDateTime.now());
    }
}

6. 重要注意事项

  1. Record 是 final 的,不能继承其他类

  2. 可以继承接口

    java 复制代码
    public record Person(String name, int age) implements Serializable, Comparable<Person> {
        @Override
        public int compareTo(Person other) {
            return this.name.compareTo(other.name);
        }
    }
  3. 可以有静态字段和方法

  4. 不能有实例字段(除自动生成的)

  5. 可以嵌套和泛型化

    java 复制代码
    public record Pair<T, U>(T first, U second) {}

7. 适用场景

✅ 适合使用:

  • DTO(数据传输对象)
  • 值对象(Value Objects)
  • 不可变数据容器
  • 方法返回多个值
  • 临时数据存储

❌ 不适合:

  • 需要可变状态
  • 需要继承其他类
  • 需要复杂的业务逻辑
  • 需要序列化特殊处理

8. Java 21+ 增强

java 复制代码
// 解构模式匹配
switch (obj) {
    case Point(int x, int y) -> System.out.printf("点(%d, %d)", x, y);
    case User(String name, int age) -> System.out.println(name);
    default -> {}
}

总结

Records 大大简化了数据载体的创建,减少了样板代码,增强了代码可读性和安全性。建议在以下情况优先使用 Record:

  1. 数据建模(DTO、VO)
  2. 方法返回多个值
  3. 需要值语义的简单类
  4. 不可变数据容器

但要注意,Record 不是所有场景的替代品,复杂的业务逻辑类仍然应该使用完整的类定义。

相关推荐
Leinwin2 小时前
OpenClaw 多 Agent 协作框架的并发限制与企业化规避方案痛点直击
java·运维·数据库
薛定谔的悦2 小时前
MQTT通信协议业务层实现的完整开发流程
java·后端·mqtt·struts
enjoy嚣士3 小时前
springboot之Exel工具类
java·spring boot·后端·easyexcel·excel工具类
罗超驿3 小时前
独立实现双向链表_LinkedList
java·数据结构·链表·linkedlist
盐水冰4 小时前
【烘焙坊项目】后端搭建(12) - 订单状态定时处理,来单提醒和顾客催单
java·后端·学习
凸头4 小时前
CompletableFuture 与 Future 对比与实战示例
java·开发语言
wuqingshun3141594 小时前
线程安全需要保证几个基本特征
java·开发语言·jvm
努力也学不会java4 小时前
【缓存算法】一篇文章带你彻底搞懂面试高频题LRU/LFU
java·数据结构·人工智能·算法·缓存·面试
攒了一袋星辰4 小时前
高并发强一致性顺序号生成系统 -- SequenceGenerator
java·数据库·mysql
小涛不学习4 小时前
Spring Boot 详解(从入门到原理)
java·spring boot·后端