一、现代Java类型系统的革命性演进
Java 14引入的记录类(Record)和Java 17引入的Sealed类(密封类)彻底改变了我们构建领域模型的方式。这些特性结合模式匹配,为构建类型安全、表达力强的领域驱动设计系统提供了强大工具。
新旧特性对比:
| 特性 | 传统方式 | 记录类+Sealed类 |
|---|---|---|
| 不可变对象 | 大量样板代码 | 自动生成所有方法 |
| 类型安全 | 运行时检查 | 编译时保证 |
| 模式匹配 | instanceof + 强制转换 | 类型模式直接解构 |
| 可维护性 | 容易出错 | 编译器辅助验证 |
二、记录类深度解析与高级用法
1. 基础记录类定义
// 基础记录类 - 自动生成constructor, getters, equals, hashCode, toString
public record User(
Long id,
String username,
String email,
LocalDateTime createdAt
) {
// 紧凑构造函数 - 用于验证逻辑
public User {
if (id == null || id <= 0) {
throw new IllegalArgumentException("ID必须为正数");
}
if (username == null || username.trim().isEmpty()) {
throw new IllegalArgumentException("用户名不能为空");
}
email = email == null ? "" : email.toLowerCase();
}
// 自定义方法
public boolean isEmailVerified() {
return !email.isEmpty();
}
// 静态工厂方法
public static User of(String username, String email) {
return new User(null, username, email, LocalDateTime.now());
}
}
// 使用示例
User user = new User(1L, "john_doe", "john@example.com", LocalDateTime.now());
User createdUser = User.of("jane_doe", "jane@example.com");
2. 记录类与接口组合
// 定义领域接口
public interface DomainEntity {
Long getId();
LocalDateTime getCreatedAt();
default boolean isNew() {
return getId() == null;
}
}
// 记录类实现接口
public record Product(
Long id,
String name,
BigDecimal price,
ProductCategory category,
LocalDateTime createdAt
) implements DomainEntity {
// 验证业务规则
public Product {
if (price == null || price.compareTo(BigDecimal.ZERO) < 0) {
throw new IllegalArgumentException("价格必须为非负数");
}
if (category == null) {
throw new IllegalArgumentException("产品分类不能为空");
}
}
// 业务方法
public Product applyDiscount(BigDecimal discountRate) {
if (discountRate.compareTo(BigDecimal.ZERO) 0) {
throw new IllegalArgumentException("折扣率必须在0-1之间");
}
BigDecimal newPrice = price.multiply(BigDecimal.ONE.subtract(discountRate));
return new Product(id, name, newPrice, category, createdAt);
}
}
3. 记录类的高级模式
// 嵌套记录类
public record Order(
Long id,
Customer customer,
List items,
OrderStatus status,
LocalDateTime orderDate
) {
// 计算属性
public BigDecimal getTotalAmount() {
return items.stream()
.map(OrderItem::getSubtotal)
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
public record OrderItem(
Product product,
Integer quantity,
BigDecimal unitPrice
) {
public OrderItem {
if (quantity == null || quantity <= 0) {
throw new IllegalArgumentException("数量必须为正数");
}
if (unitPrice == null || unitPrice.compareTo(BigDecimal.ZERO) < 0) {
throw new IllegalArgumentException("单价必须为非负数");
}
}
public BigDecimal getSubtotal() {
return unitPrice.multiply(BigDecimal.valueOf(quantity));
}
}
}
// 使用构建器模式增强记录类
public class UserBuilder {
private Long id;
private String username;
private String email;
private LocalDateTime createdAt = LocalDateTime.now();
public UserBuilder id(Long id) {
this.id = id;
return this;
}
public UserBuilder username(String username) {
this.username = username;
return this;
}
public UserBuilder email(String email) {
this.email = email;
return this;
}
public User build() {
return new User(id, username, email, createdAt);
}
}
三、Sealed类实战:构建类型安全的领域模型
1. 密封接口与实现
// 定义密封接口
public sealed interface PaymentMethod
permits CreditCard, BankTransfer, DigitalWallet {
String getAccountNumber();
BigDecimal getBalance();
PaymentResult processPayment(BigDecimal amount);
}
// 具体的支付方式实现
public record CreditCard(
String cardNumber,
String cardHolder,
LocalDate expiryDate,
String cvv,
BigDecimal balance
) implements PaymentMethod {
public String getAccountNumber() {
return cardNumber;
}
public PaymentResult processPayment(BigDecimal amount) {
if (balance.compareTo(amount) < 0) {
return new PaymentResult(false, "余额不足");
}
// 信用卡支付逻辑
return new PaymentResult(true, "支付成功");
}
}
public record BankTransfer(
String accountNumber,
String bankName,
String accountHolder,
BigDecimal balance
) implements PaymentMethod {
public PaymentResult processPayment(BigDecimal amount) {
// 银行转账逻辑
return new PaymentResult(true, "转账处理中");
}
}
public record DigitalWallet(
String walletId,
String provider,
BigDecimal balance
) implements PaymentMethod {
public String getAccountNumber() {
return walletId;
}
public PaymentResult processPayment(BigDecimal amount) {
// 数字钱包支付逻辑
return new PaymentResult(true, "钱包支付成功");
}
}
2. 密封类与模式匹配结合
// 支付处理服务
@Service
public class PaymentProcessingService {
public PaymentResponse processOrderPayment(Order order, PaymentMethod paymentMethod) {
PaymentResult result = paymentMethod.processPayment(order.getTotalAmount());
// 使用模式匹配处理不同类型的支付结果
return switch (paymentMethod) {
case CreditCard card -> handleCreditCardPayment(card, result, order);
case BankTransfer transfer -> handleBankTransfer(transfer, result, order);
case DigitalWallet wallet -> handleDigitalWallet(wallet, result, order);
// 不需要default分支,编译器知道所有情况都已覆盖
};
}
private PaymentResponse handleCreditCardPayment(
CreditCard card, PaymentResult result, Order order) {
if (result.success()) {
// 发送信用卡支付确认
notificationService.sendCreditCardConfirmation(card.cardHolder(), order);
}
return new PaymentResponse(result.success(), result.message(), "CREDIT_CARD");
}
private PaymentResponse handleBankTransfer(
BankTransfer transfer, PaymentResult result, Order order) {
// 生成银行转账参考号
String referenceNumber = generateBankReference(transfer, order);
return new PaymentResponse(result.success(), referenceNumber, "BANK_TRANSFER");
}
private PaymentResponse handleDigitalWallet(
DigitalWallet wallet, PaymentResult result, Order order) {
if (result.success()) {
// 记录钱包交易
walletService.recordTransaction(wallet.walletId(), order.getTotalAmount());
}
return new PaymentResponse(result.success(), result.message(), "DIGITAL_WALLET");
}
}
四、DDD领域建模实战:电商系统完整案例
1. 值对象建模
// 地址值对象
public record Address(
String street,
String city,
String state,
String zipCode,
String country
) {
public Address {
Objects.requireNonNull(street, "街道不能为空");
Objects.requireNonNull(city, "城市不能为空");
Objects.requireNonNull(country, "国家不能为空");
if (street.trim().isEmpty()) {
throw new IllegalArgumentException("街道不能为空");
}
}
public String getFullAddress() {
return String.format("%s, %s, %s %s, %s", street, city, state, zipCode, country);
}
public boolean isDomestic() {
return "US".equals(country);
}
}
// 货币值对象
public record Money(
BigDecimal amount,
Currency currency
) implements Comparable {
public Money {
Objects.requireNonNull(amount, "金额不能为空");
Objects.requireNonNull(currency, "货币类型不能为空");
if (amount.compareTo(BigDecimal.ZERO) < 0) {
throw new IllegalArgumentException("金额不能为负数");
}
// 标准化金额精度
amount = amount.setScale(currency.getDefaultFractionDigits(), RoundingMode.HALF_EVEN);
}
public Money add(Money other) {
validateSameCurrency(other);
return new Money(amount.add(other.amount), currency);
}
public Money subtract(Money other) {
validateSameCurrency(other);
return new Money(amount.subtract(other.amount), currency);
}
public Money multiply(BigDecimal multiplier) {
return new Money(amount.multiply(multiplier), currency);
}
private void validateSameCurrency(Money other) {
if (!this.currency.equals(other.currency)) {
throw new IllegalArgumentException("货币类型不匹配");
}
}
@Override
public int compareTo(Money other) {
validateSameCurrency(other);
return this.amount.compareTo(other.amount);
}
}
2. 聚合根设计
// 订单聚合根
public record OrderAggregate(
OrderId id,
CustomerId customerId,
Address shippingAddress,
List orderLines,
OrderStatus status,
Money totalAmount,
LocalDateTime createdDate,
LocalDateTime updatedDate
) {
public OrderAggregate {
Objects.requireNonNull(id, "订单ID不能为空");
Objects.requireNonNull(customerId, "客户ID不能为空");
Objects.requireNonNull(orderLines, "订单项不能为空");
Objects.requireNonNull(status, "订单状态不能为空");
if (orderLines.isEmpty()) {
throw new IllegalArgumentException("订单必须包含至少一个订单项");
}
// 计算总金额
totalAmount = calculateTotalAmount(orderLines);
}
private static Money calculateTotalAmount(List orderLines) {
return orderLines.stream()
.map(OrderLine::getLineTotal)
.reduce(Money.zero(Currency.getInstance("USD")), Money::add);
}
// 领域命令
public OrderAggregate applyDiscount(Discount discount) {
Money discountedAmount = discount.applyTo(totalAmount);
return new OrderAggregate(
id, customerId, shippingAddress, orderLines,
status, discountedAmount, createdDate, LocalDateTime.now()
);
}
public OrderAggregate cancel() {
if (status == OrderStatus.SHIPPED || status == OrderStatus.DELIVERED) {
throw new IllegalStateException("已发货或已送达的订单不能取消");
}
return new OrderAggregate(
id, customerId, shippingAddress, orderLines,
OrderStatus.CANCELLED, totalAmount, createdDate, LocalDateTime.now()
);
}
}
// 订单项值对象
public record OrderLine(
ProductId productId,
String productName,
Integer quantity,
Money unitPrice
) {
public Money getLineTotal() {
return unitPrice.multiply(BigDecimal.valueOf(quantity));
}
}
五、模式匹配高级技巧与实战
1. 类型模式与记录模式
// 复杂的模式匹配示例
public class OrderProcessor {
public ProcessingResult processOrder(OrderAggregate order) {
return switch (order.status()) {
case OrderStatus.PENDING pending -> processPendingOrder(order, pending);
case OrderStatus.PAID paid -> processPaidOrder(order, paid);
case OrderStatus.SHIPPED shipped -> processShippedOrder(order, shipped);
case OrderStatus.CANCELLED cancelled -> processCancelledOrder(order, cancelled);
case OrderStatus.DELIVERED delivered -> processDeliveredOrder(order, delivered);
};
}
// 记录模式 - 解构记录类
public String formatOrderSummary(Object order) {
return switch (order) {
case OrderAggregate(var id, var customerId, var address,
var orderLines, var status, var totalAmount,
var createdDate, var updatedDate) ->
String.format("订单 %s - 总金额: %s - 状态: %s",
id.value(), totalAmount, status);
case null -> "订单为空";
default -> "未知订单类型";
};
}
// 守卫模式
public boolean canApplyDiscount(OrderAggregate order, Discount discount) {
return switch (order) {
case OrderAggregate o when o.totalAmount().compareTo(Money.of(100, "USD")) > 0 ->
discount.isApplicableToLargeOrders();
case OrderAggregate o when o.orderLines().size() > 5 ->
discount.isApplicableToMultiItemOrders();
default -> discount.isApplicable();
};
}
}
// 嵌套模式匹配
public class ShippingCalculator {
public Money calculateShippingCost(OrderAggregate order) {
return switch (order) {
case OrderAggregate(_, _, Address(_, _, _, _, var country),
var orderLines, _, var totalAmount, _, _)
when "US".equals(country) -> {
if (totalAmount.compareTo(Money.of(50, "USD")) > 0) {
yield Money.zero(Currency.getInstance("USD")); // 免费配送
} else if (orderLines.size() > 3) {
yield Money.of(5.99, "USD"); // 多件商品优惠配送
} else {
yield Money.of(9.99, "USD"); // 标准配送
}
}
case OrderAggregate(_, _, Address(_, _, _, _, var country), _, _, _, _)
when !"US".equals(country) -> {
// 国际配送逻辑
yield Money.of(29.99, "USD");
}
default -> throw new IllegalArgumentException("无法计算配送费用");
};
}
}
六、性能优化与最佳实践
1. 记录类性能优势
@State(Scope.Benchmark)
@BenchmarkMode(Mode.Throughput)
public class RecordPerformanceBenchmark {
private List recordUsers;
private List legacyUsers;
@Setup
public void setup() {
recordUsers = IntStream.range(0, 1000)
.mapToObj(i -> new User((long) i, "user" + i, "user" + i + "@test.com", LocalDateTime.now()))
.toList();
legacyUsers = IntStream.range(0, 1000)
.mapToObj(i -> new LegacyUser((long) i, "user" + i, "user" + i + "@test.com", LocalDateTime.now()))
.toList();
}
@Benchmark
public long recordHashCodePerformance() {
return recordUsers.stream()
.mapToInt(User::hashCode)
.sum();
}
@Benchmark
public long legacyHashCodePerformance() {
return legacyUsers.stream()
.mapToInt(LegacyUser::hashCode)
.sum();
}
}
// 传统Java类对比
class LegacyUser {
private final Long id;
private final String username;
private final String email;
private final LocalDateTime createdAt;
// 大量样板代码...
// constructors, getters, equals, hashCode, toString
}
2. 最佳实践总结
- 记录类适用场景:数据传输对象、值对象、不可变配置、方法返回多个值
- Sealed类适用场景:定义有限的继承层次、状态机、表达式树、领域事件
- 性能优势:减少内存占用、更快的hashCode/equals、更好的内联优化
- 设计原则:优先使用记录类表示数据、使用密封类限制继承、结合模式匹配处理多态
3. 迁移策略建议
// 迁移步骤示例
public class MigrationStrategy {
// 1. 识别适合的记录类候选
// - 主要是数据的类
// - 不可变对象
// - 需要值语义的类
// 2. 识别适合的密封类候选
// - 有限的子类层次
// - 需要编译时类型安全的场景
// - 模式匹配的目标类型
// 3. 渐进式迁移
// - 从核心领域模型开始
// - 保持向后兼容性
// - 逐步替换传统实现
}
总结与展望
Java记录类和Sealed类的引入标志着Java语言在现代化道路上的重要里程碑:
- 开发效率革命:大幅减少样板代码,提升开发速度
- 类型安全增强:编译时保证,减少运行时错误
- 领域表达力:更贴近业务语言的代码结构
- 性能优化:更好的内存使用和运行时性能
未来发展方向:
- 更多语言特性与记录类/Sealed类的深度集成
- 框架和库对新型类的原生支持
- 更强大的模式匹配能力
- 工具链的持续优化和改进
掌握记录类和Sealed类不仅能够编写更简洁、更安全的代码,更重要的是能够构建更加健壮、更易维护的领域驱动设计系统,为复杂业务场景提供坚实的技术基础。

