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

相关推荐
LiRuiJie2 小时前
深入剖析RocketMQ
java·rocketmq
BlockChain8882 小时前
SpringBoot实战一:10分钟搭建企业级用户管理系统(20000字完整项目)
java·spring boot·后端
消失的旧时光-19432 小时前
第六课 · 6.1 从 JDBC 到 MyBatis:SQL 工程化是如何发生的?
java·sql·mybatis
Jaxson Lin2 小时前
Java编程进阶:线程基础与实现方式全解析
java·开发语言
夜喵YM2 小时前
基于 Spire.XLS.Free for Java 实现无水印 Excel 转 PDF
java·pdf·excel
茶本无香2 小时前
设计模式之五—门面模式:简化复杂系统的统一接口
java·设计模式
她说可以呀2 小时前
网络基础初识
java·网络·java-ee
没有bug.的程序员2 小时前
Java锁优化:从synchronized到CAS的演进与实战选择
java·开发语言·多线程·并发·cas·synchronized·
麦兜*2 小时前
SpringBoot Profile多环境配置详解,一套配置应对所有场景
java·数据库·spring boot