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

相关推荐
寻星探路5 小时前
【深度长文】万字攻克网络原理:从 HTTP 报文解构到 HTTPS 终极加密逻辑
java·开发语言·网络·python·http·ai·https
曹牧7 小时前
Spring Boot:如何测试Java Controller中的POST请求?
java·开发语言
爬山算法8 小时前
Hibernate(90)如何在故障注入测试中使用Hibernate?
java·后端·hibernate
kfyty7258 小时前
集成 spring-ai 2.x 实践中遇到的一些问题及解决方案
java·人工智能·spring-ai
猫头虎8 小时前
如何排查并解决项目启动时报错Error encountered while processing: java.io.IOException: closed 的问题
java·开发语言·jvm·spring boot·python·开源·maven
李少兄8 小时前
在 IntelliJ IDEA 中修改 Git 远程仓库地址
java·git·intellij-idea
忆~遂愿9 小时前
ops-cv 算子库深度解析:面向视觉任务的硬件优化与数据布局(NCHW/NHWC)策略
java·大数据·linux·人工智能
小韩学长yyds9 小时前
Java序列化避坑指南:明确这4种场景,再也不盲目实现Serializable
java·序列化
仟濹9 小时前
【Java基础】多态 | 打卡day2
java·开发语言