Java17新特性解析记录类、密封类与模式匹配的实战应用

# 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在数据建模、模式匹配和类型安全方面的能力,使开发者能够编写更简洁、更安全、更易维护的代码。

根据原作 https://pan.quark.cn/s/459657bcfd45 的源码改编 Classic-ML-Methods-Algo 引言 建立这个项目,是为了梳理和总结传统机器学习(Machine Learning)方法(methods)或者算法(algo),和各位同仁相互学习交流. 现在的深度学习本质上来自于传统的神经网络模型,很大程度上是传统机器学习的延续,同时也在不少时候需要结合传统方法来实现. 任何机器学习方法基本的流程结构都是通用的;使用的评价方法也基本通用;使用的一些数学知识也是通用的. 本文在梳理传统机器学习方法算法的同时也会顺便补充这些流程,数学上的知识以供参考. 机器学习 机器学习是人工智能(Artificial Intelligence)的一个分支,也是实现人工智能最重要的手段.区别于传统的基于规则(rule-based)的算法,机器学习可以从数据中获取知识,从而实现规定的任务[Ian Goodfellow and Yoshua Bengio and Aaron Courville的Deep Learning].这些知识可以分为四种: 总结(summarization) 预测(prediction) 估计(estimation) 假想验证(hypothesis testing) 机器学习主要关心的是预测[Varian在Big Data : New Tricks for Econometrics],预测的可以是连续性的输出变量,分,聚或者物品之间的有趣关联. 机器学习分 根据数据配置(setting,是否有标签,可以是连续的也可以是离散的)和任务目标,我们可以将机器学习方法分为四种: 无监督(unsupervised) 训练数据没有给定...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值