Java记录类(Record)深度解析:不可变数据建模与模式匹配实战
一、记录类核心特性
Java 16正式引入的透明数据载体:
// 基础记录类定义
public record Point(int x, int y) {
// 紧凑构造器
public Point {
if (x < 0 || y < 0) {
throw new IllegalArgumentException("坐标不能为负数");
}
}
// 添加派生方法
public double distanceFromOrigin() {
return Math.hypot(x, y);
}
}
// 使用示例
Point p = new Point(3, 4);
System.out.println(p.x()); // 自动生成的访问器
System.out.println(p); // 自动生成的toString()
Point copied = new Point(p.x(), p.y()); // 显式复制
核心优势:简洁语法、不可变性、自动实现、模式匹配友好
二、高级应用模式
1. 嵌套记录结构
// 复杂领域模型建模
public record Order(
String orderId,
Customer customer,
List items,
LocalDateTime createdAt
) {
// 静态工厂方法
public static Order create(String orderId, Customer customer) {
return new Order(orderId, customer, new ArrayList(), LocalDateTime.now());
}
// 业务逻辑方法
public BigDecimal totalAmount() {
return items.stream()
.map(LineItem::subtotal)
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
}
public record Customer(
String customerId,
String name,
Address shippingAddress,
Address billingAddress
) {}
public record LineItem(
Product product,
int quantity,
BigDecimal unitPrice
) {
public BigDecimal subtotal() {
return unitPrice.multiply(new BigDecimal(quantity));
}
}
2. 模式匹配应用
// instanceof模式匹配
public String processShape(Shape shape) {
if (shape instanceof Circle c) {
return String.format("圆形 半径=%.2f", c.radius());
} else if (shape instanceof Rectangle r) {
return String.format("矩形 宽=%.2f 高=%.2f", r.width(), r.height());
}
return "未知形状";
}
// switch表达式模式匹配(Java 21+)
public double calculateArea(Shape shape) {
return switch (shape) {
case Circle c -> Math.PI * c.radius() * c.radius();
case Rectangle r -> r.width() * r.height();
case Triangle t -> 0.5 * t.base() * t.height();
default -> throw new IllegalArgumentException("不支持的形状");
};
}
// 记录模式解构(Java 21+)
public void printCoordinates(Object obj) {
if (obj instanceof Point(int x, int y)) {
System.out.printf("坐标: (%d, %d)%n", x, y);
}
}
三、序列化与持久化
1. JSON序列化方案
// Jackson配置
public class RecordModule extends SimpleModule {
public RecordModule() {
setMixInAnnotation(Point.class, PointMixin.class);
}
abstract static class PointMixin {
@JsonCreator
public PointMixin(@JsonProperty("x") int x,
@JsonProperty("y") int y) {}
}
}
// 使用示例
ObjectMapper mapper = new ObjectMapper()
.registerModule(new RecordModule())
.registerModule(new JavaTimeModule());
Point point = new Point(3, 4);
String json = mapper.writeValueAsString(point);
Point deserialized = mapper.readValue(json, Point.class);
2. JPA持久化策略
// JPA实体适配方案
@Entity
@Table(name = "orders")
public class OrderEntity {
@Id
private String orderId;
@Embedded
private Customer customer;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
private List items = new ArrayList();
// 转换为记录类
public Order toRecord() {
return new Order(
orderId,
customer.toRecord(),
items.stream().map(LineItemEntity::toRecord).toList(),
createdAt
);
}
// 从记录类更新
public void updateFromRecord(Order order) {
this.items.clear();
order.items().forEach(item ->
this.items.add(LineItemEntity.fromRecord(item)));
}
}
// 使用示例
Order order = orderRepository.findById(id)
.map(OrderEntity::toRecord)
.orElseThrow();
四、领域驱动设计实战
1. 电商订单系统建模
// 核心领域模型
public record Order(
OrderId id,
CustomerId customerId,
OrderStatus status,
List items,
Address shippingAddress,
Money totalAmount,
Instant createdTime
) {
public enum OrderStatus { DRAFT, PAID, SHIPPED, COMPLETED, CANCELLED }
// 领域行为
public Order addItem(Product product, int quantity) {
List newItems = new ArrayList(items);
newItems.add(new OrderItem(
product.id(),
product.name(),
product.price(),
quantity
));
return new Order(
id, customerId, status, newItems,
shippingAddress, calculateTotal(newItems), createdTime
);
}
public Order cancel() {
if (status != OrderStatus.DRAFT) {
throw new IllegalStateException("只能取消草稿订单");
}
return new Order(
id, customerId, OrderStatus.CANCELLED,
items, shippingAddress, totalAmount, createdTime
);
}
}
// 值对象记录
public record Money(BigDecimal amount, Currency currency) {
public Money add(Money other) {
if (!currency.equals(other.currency)) {
throw new IllegalArgumentException("币种不一致");
}
return new Money(amount.add(other.amount), currency);
}
}
五、性能与兼容性指南
- 内存占用:记录类比传统类节省20-30%内存
- 反射限制:自动生成的字段为final且不可修改
- 序列化:需要特殊处理构造函数逻辑
- 模式匹配:Java 21+提供完整解构能力
- 向后兼容:记录类可逐步替换传统DTO