# Java 17新特性解析:记录类、密封类与模式匹配的实战应用
## 记录类(Records)
记录类是Java 16中引入的预览特性,在Java 17中成为正式特性。它提供了一种简洁的语法来声明主要用于存储数据的类。
### 基本语法与特性
```java
// 传统Java类
public final class Person {
private final String name;
private final int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// getters, equals, hashCode, toString等方法
}
// 使用记录类
public record Person(String name, int age) { }
```
记录类自动生成:
- 所有字段的getter方法(方法名与字段名相同)
- equals()、hashCode()和toString()方法
- 规范的构造函数
### 实战应用场景
1. DTO(数据传输对象)
```java
// API响应对象
public record ApiResponse(boolean success, String message, T data) { }
// 使用示例
public class UserService {
public ApiResponse getUserById(Long id) {
try {
User user = userRepository.findById(id);
return new ApiResponse<>(true, Success, user);
} catch (Exception e) {
return new ApiResponse<>(false, e.getMessage(), null);
}
}
}
```
2. 配置参数封装
```java
public record DatabaseConfig(
String url,
String username,
String password,
int poolSize
) {
// 自定义构造函数进行验证
public DatabaseConfig {
if (poolSize <= 0) {
throw new IllegalArgumentException(连接池大小必须大于0);
}
}
// 静态工厂方法
public static DatabaseConfig fromProperties(Properties props) {
return new DatabaseConfig(
props.getProperty(db.url),
props.getProperty(db.username),
props.getProperty(db.password),
Integer.parseInt(props.getProperty(db.poolSize, 10))
);
}
}
```
3. 方法返回多个值
```java
public record ValidationResult(boolean isValid, String errorMessage) { }
public class UserValidator {
public ValidationResult validate(User user) {
if (user.name() == null || user.name().trim().isEmpty()) {
return new ValidationResult(false, 用户名不能为空);
}
if (user.age() < 0) {
return new ValidationResult(false, 年龄不能为负数);
}
return new ValidationResult(true, null);
}
}
```
## 密封类(Sealed Classes)
密封类允许开发者精确控制哪些类可以继承或实现它,这是在Java 17中成为正式特性的重要功能。
### 基本语法
```java
// 定义密封类
public sealed abstract class Shape
permits Circle, Rectangle, Triangle {
public abstract double area();
}
// 允许的子类
public final class Circle extends Shape {
private final double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
public double area() {
return Math.PI radius radius;
}
}
public final class Rectangle extends Shape {
private final double width;
private final double height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
@Override
public double area() {
return width height;
}
}
public non-sealed class Triangle extends Shape {
private final double base;
private final double height;
public Triangle(double base, double height) {
this.base = base;
this.height = height;
}
@Override
public double area() {
return 0.5 base height;
}
}
```
### 实战应用场景
1. 状态机实现
```java
// 订单状态密封类
public sealed interface OrderState
permits OrderState.Pending, OrderState.Confirmed,
OrderState.Shipped, OrderState.Delivered, OrderState.Cancelled {
record Pending() implements OrderState {}
record Confirmed() implements OrderState {}
record Shipped(String trackingNumber) implements OrderState {}
record Delivered(LocalDate deliveryDate) implements OrderState {}
record Cancelled(String reason) implements OrderState {}
}
public class Order {
private String orderId;
private OrderState state;
public void confirm() {
if (state instanceof OrderState.Pending) {
state = new OrderState.Confirmed();
} else {
throw new IllegalStateException(只能在待处理状态下确认订单);
}
}
public void ship(String trackingNumber) {
if (state instanceof OrderState.Confirmed) {
state = new OrderState.Shipped(trackingNumber);
} else {
throw new IllegalStateException(只能在确认状态下发货);
}
}
}
```
2. 表达式树
```java
public sealed interface Expr
permits Expr.Constant, Expr.Plus, Expr.Minus, Expr.Times, Expr.Divide {
record Constant(double value) implements Expr {}
record Plus(Expr left, Expr right) implements Expr {}
record Minus(Expr left, Expr right) implements Expr {}
record Times(Expr left, Expr right) implements Expr {}
record Divide(Expr left, Expr right) implements Expr {}
}
public class ExpressionEvaluator {
public double evaluate(Expr expr) {
return switch (expr) {
case Expr.Constant(var value) -> value;
case Expr.Plus(var left, var right) -> evaluate(left) + evaluate(right);
case Expr.Minus(var left, var right) -> evaluate(left) - evaluate(right);
case Expr.Times(var left, var right) -> evaluate(left) evaluate(right);
case Expr.Divide(var left, var right) -> evaluate(left) / evaluate(right);
};
}
}
```
## 模式匹配
模式匹配是Java持续改进的重要方向,在Java 17中得到了显著增强。
### instanceof模式匹配
```java
// 传统写法
if (obj instanceof String) {
String str = (String) obj;
System.out.println(str.length());
}
// Java 17模式匹配
if (obj instanceof String str) {
System.out.println(str.length());
}
```
### switch表达式与模式匹配结合
```java
public class PatternMatchingDemo {
// 处理不同类型的数据
public static String format(Object obj) {
return switch (obj) {
case null -> null;
case Integer i -> String.format(整数: %d, i);
case Long l -> String.format(长整数: %d, l);
case Double d -> String.format(浮点数: %.2f, d);
case String s -> String.format(字符串: %s, s);
case int[] array -> String.format(整数数组, 长度: %d, array.length);
default -> obj.toString();
};
}
// 结合记录类的模式匹配
public static double calculateArea(Shape shape) {
return switch (shape) {
case Circle(var radius) -> Math.PI radius radius;
case Rectangle(var width, var height) -> width height;
case Triangle(var base, var height) -> 0.5 base height;
};
}
// 复杂的模式匹配
public static String processShape(Shape shape) {
return switch (shape) {
case Circle c when c.radius() > 10 -> 大圆形;
case Circle c when c.radius() <= 10 -> 小圆形;
case Rectangle r when r.width() == r.height() -> 正方形;
case Rectangle r -> 长方形;
case Triangle t -> 三角形;
};
}
}
```
## 综合实战案例:电商系统
下面通过一个电商系统的例子来展示这些特性的综合应用:
```java
// 定义领域模型
public record Product(String id, String name, BigDecimal price, Category category) {}
public record Customer(String id, String name, String email, CustomerLevel level) {}
public sealed interface OrderEvent
permits OrderEvent.Created, OrderEvent.Paid,
OrderEvent.Shipped, OrderEvent.Delivered, OrderEvent.Cancelled {
record Created(String orderId, LocalDateTime timestamp) implements OrderEvent {}
record Paid(String orderId, BigDecimal amount, LocalDateTime timestamp) implements OrderEvent {}
record Shipped(String orderId, String trackingNumber, LocalDateTime timestamp) implements OrderEvent {}
record Delivered(String orderId, LocalDateTime timestamp) implements OrderEvent {}
record Cancelled(String orderId, String reason, LocalDateTime timestamp) implements OrderEvent {}
}
// 订单处理服务
public class OrderProcessor {
public void processEvent(OrderEvent event) {
switch (event) {
case OrderEvent.Created(var orderId, var timestamp) ->
handleOrderCreated(orderId, timestamp);
case OrderEvent.Paid(var orderId, var amount, var timestamp) ->
handleOrderPaid(orderId, amount, timestamp);
case OrderEvent.Shipped(var orderId, var trackingNumber, var timestamp) ->
handleOrderShipped(orderId, trackingNumber, timestamp);
case OrderEvent.Delivered(var orderId, var timestamp) ->
handleOrderDelivered(orderId, timestamp);
case OrderEvent.Cancelled(var orderId, var reason, var timestamp) ->
handleOrderCancelled(orderId, reason, timestamp);
}
}
private void handleOrderCreated(String orderId, LocalDateTime timestamp) {
System.out.printf(订单 %s 在 %s 创建%n, orderId, timestamp);
}
private void handleOrderPaid(String orderId, BigDecimal amount, LocalDateTime timestamp) {
System.out.printf(订单 %s 在 %s 支付了 %s%n, orderId, timestamp, amount);
}
// 其他处理方法...
}
// 价格计算器
public class PricingCalculator {
public record PriceResult(BigDecimal originalPrice, BigDecimal discount, BigDecimal finalPrice) {
public PriceResult {
if (finalPrice.compareTo(BigDecimal.ZERO) < 0) {
throw new IllegalArgumentException(最终价格不能为负数);
}
}
}
public PriceResult calculatePrice(Product product, Customer customer) {
BigDecimal originalPrice = product.price();
BigDecimal discount = calculateDiscount(product, customer);
BigDecimal finalPrice = originalPrice.subtract(discount).max(BigDecimal.ZERO);
return new PriceResult(originalPrice, discount, finalPrice);
}
private BigDecimal calculateDiscount(Product product, Customer customer) {
return switch (customer.level()) {
case VIP -> product.price().multiply(new BigDecimal(0.2));
case GOLD -> product.price().multiply(new BigDecimal(0.15));
case SILVER -> product.price().multiply(new BigDecimal(0.1));
case REGULAR -> BigDecimal.ZERO;
};
}
}
```
## 最佳实践与注意事项
1. 记录类适用场景:
- 主要用于数据传输的不可变对象
- 不需要复杂业务逻辑的简单值对象
- 避免在需要大量继承或复杂行为的场景中使用
2. 密封类设计原则:
- 明确规划类的继承层次
- 在编译时捕获不合法的子类
- 与模式匹配结合使用效果最佳
3. 模式匹配优势:
- 减少类型转换的样板代码
- 提高代码的可读性和安全性
- 编译时检查模式完整性
4. 性能考虑:
- 记录类在大多数情况下性能优于传统POJO
- 模式匹配在switch表达式中性能优秀
- 密封类有助于JVM进行优化
这些新特性共同提升了Java在数据建模、模式匹配和类型安全方面的能力,使开发者能够编写更简洁、更安全、更易维护的代码。
839

被折叠的 条评论
为什么被折叠?



