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 不是所有场景的替代品,复杂的业务逻辑类仍然应该使用完整的类定义。

相关推荐
邪修king3 小时前
Re:Linux 系统篇(三十五):进程间通信Chapter2:从匿名管道到进程池:Linux 进程间通信实战(深度理解「先描述,再组织」)
java·linux·运维
拆房老料4 小时前
【第四部分:Agentic 智能体设计模式】16. 一个 Prompt 搞不定复杂任务?试试 Prompt Chaining
java·前端·人工智能·设计模式·prompt
张张123y4 小时前
后端第十四课:Agent 记忆系统(让 Agent 记住上下文和用户,跨会话不健忘)
java·大数据·人工智能·python·agent·记忆
曹牧9 小时前
C#:空合并运算符
java·前端·数据库
布吉岛的石头9 小时前
Java 程序员第 50 阶段2:预训练的目标函数:自回归语言建模本质
java·开发语言·人工智能·深度学习·回归·transformer
golang学习记9 小时前
IDEA 2026年的玩法已经完全不同
java·ide·intellij-idea
紧跟先前的步伐10 小时前
Go AI Agent 实战 05|Temperature 与生成参数:让模型输出可控
java·人工智能·golang
金銀銅鐵10 小时前
[Java] 展示添加元素时 ArrayList 的内部变化
java·后端·ai编程
斌糖雪梨10 小时前
spring auth 核心流程详解
java·后端·spring
文丑颜不良啊12 小时前
LeetCode201~225题目解析
java·leetcode