Java新特性:Records与Sealed Classes实战指南

一、Records(记录类)

核心价值:简化不可变数据载体的声明,自动生成equals()hashCode()toString()等方法。

语法结构

record 类名(参数列表) { 
    // 可选:自定义方法或构造函数
}

实战示例:地理坐标系统

// 定义记录类
record GeoPoint(double latitude, double longitude) {
    // 自定义验证逻辑
    public GeoPoint {
        if (latitude < -90 || latitude > 90) 
            throw new IllegalArgumentException("纬度范围错误");
        if (longitude < -180 || longitude > 180)
            throw new IllegalArgumentException("经度范围错误");
    }
    
    // 自定义方法
    public String toDMS() {
        return String.format("%.4f°N, %.4f°E", latitude, longitude);
    }
}

// 使用示例
public static void main(String[] args) {
    GeoPoint beijing = new GeoPoint(39.9042, 116.4074);
    System.out.println(beijing);        // 自动调用toString()
    System.out.println(beijing.toDMS()); // 自定义方法
}

优势对比

传统类代码量 Records代码量
50+行 10-15行
二、Sealed Classes(密封类)

核心价值:精确控制类继承关系,限定子类范围,增强类型安全性。

语法结构

public sealed class 基类名 permits 子类1, 子类2... {
    // 基类实现
}

实战示例:图形计算系统

// 1. 定义密封基类
public sealed class Shape permits Circle, Rectangle, Triangle {
    public abstract double area();
}

// 2. 定义许可子类
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;  // $$ A = \pi r^2 $$
    }
}

public record Rectangle(double width, double height) extends Shape {
    @Override
    public double area() {
        return width * height;  // $$ A = w \times h $$
    }
}

public final class Triangle extends Shape {
    private final double base, height;
    
    public Triangle(double base, double height) {
        this.base = base;
        this.height = height;
    }
    
    @Override
    public double area() {
        return 0.5 * base * height;  // $$ A = \frac{1}{2} b h $$
    }
}

// 3. 使用模式匹配(Java 17+)
static void printArea(Shape shape) {
    switch (shape) {
        case Circle c -> System.out.println("圆面积: " + c.area());
        case Rectangle r -> System.out.println("矩形面积: " + r.area());
        case Triangle t -> System.out.println("三角形面积: " + t.area());
        // 无需default分支,编译器知道所有子类
    }
}

三、组合实战:API响应系统
// 1. 定义密封响应基类
public sealed interface ApiResponse permits Success, Failure {
    record Success<T>(T data, String timestamp) implements ApiResponse {}
    record Failure(int code, String message) implements ApiResponse {}
}

// 2. 业务逻辑处理
public class ApiHandler {
    public ApiResponse fetchData() {
        try {
            Object data = // 获取数据逻辑
            return new ApiResponse.Success<>(data, Instant.now().toString());
        } catch (Exception e) {
            return new ApiResponse.Failure(500, "服务器错误");
        }
    }
}

// 3. 客户端处理
public class Client {
    public static void main(String[] args) {
        ApiResponse response = new ApiHandler().fetchData();
        
        if (response instanceof ApiResponse.Success success) {
            System.out.println("成功: " + success.data());
        } else if (response instanceof ApiResponse.Failure failure) {
            System.out.println("失败: " + failure.message());
        }
    }
}

四、最佳实践建议
  1. Records适用场景

    • DTO数据传输对象
    • 配置参数载体
    • 方法多返回值
    • 替代简单元组
  2. Sealed Classes适用场景

    • 状态机实现(如订单状态)
    • 表达式树处理
    • 领域模型约束
    • 替代枚举的扩展需求
  3. 组合优势

    • 类型安全:编译器验证所有子类
    • 模式匹配:简化分支处理
    • 代码精简:减少模板代码量
    • 领域表达:更贴近业务语义

升级提示:需Java 16+(Records正式版)和Java 17+(Sealed Classes正式版),建议结合jlink创建定制化运行时镜像减小部署体积。

更多推荐