Java中密封类(Sealed Classes)和记录类(Record Classes)的详细讲解

以下是对Java中**密封类(Sealed Classes)记录类(Record Classes)**的详细讲解,结合代码示例与核心特性:


一、密封类(Sealed Classes)

密封类用于限制类的继承关系,明确指定哪些类可以继承或实现它,增强代码的可控性和安全性。自Java 17起成为正式特性。

1. 核心语法

  • 使用sealed关键字声明密封类。
  • 通过permits指定允许继承的子类。
  • 子类必须使用finalsealednon-sealed修饰符。
示例代码
// 密封类声明
public sealed class Shape permits Circle, Rectangle, Triangle {
    public abstract double area();
}

// 子类必须明确修饰符
final class Circle extends Shape {
    private final double radius;
    public Circle(double r) { this.radius = r; }
    @Override public double area() { return Math.PI * radius * radius; }
}

non-sealed class Rectangle extends Shape {
    private final double width, height;
    public Rectangle(double w, double h) { this.width = w; this.height = h; }
    @Override public double area() { return width * height; }
}

sealed class Triangle extends Shape permits EquilateralTriangle {
    protected double base, height;
    @Override public double area() { return 0.5 * base * height; }
}

final class EquilateralTriangle extends Triangle {
    public EquilateralTriangle(double side) { 
        this.base = side; 
        this.height = (Math.sqrt(3)/2) * side; 
    }
}

2. 关键规则

  1. 继承限制:只有permits列出的类可以继承密封类。
  2. 子类修饰符
    • final:禁止进一步继承。
    • sealed:子类继续密封,需指定新的permits列表。
    • non-sealed:解除密封限制,允许任意继承。
  3. 包与模块:密封类及其子类需位于同一包或模块中。

3. 应用场景

  • 精确建模:如几何形状仅允许特定子类。
  • 模式匹配:结合switch表达式确保所有子类覆盖。
  • API设计:限制第三方扩展,避免不可控继承。

二、记录类(Record Classes)

记录类用于简化不可变数据类的定义,自动生成构造函数、访问器和工具方法(如equalshashCode)。自Java 16起成为正式特性。

1. 核心语法

  • 使用record关键字声明。
  • 组件(字段)隐式声明为private final
  • 自动生成规范构造函数、toString()equals()hashCode()
示例代码
// 声明记录类
public record Person(String name, int age) {
    // 可添加静态字段或方法
    public static final int MAX_AGE = 120;

    // 紧凑构造函数(参数校验)
    public Person {
        if (age < 0 || age > MAX_AGE) {
            throw new IllegalArgumentException("Invalid age");
        }
    }

    // 自定义实例方法
    public String greet() {
        return "Hello, I'm " + name;
    }
}

// 使用记录类
public class Main {
    public static void main(String[] args) {
        Person p1 = new Person("Alice", 30);
        Person p2 = new Person("Bob", 25);
        
        System.out.println(p1.name());    // 输出:Alice
        System.out.println(p1.equals(p2)); // 输出:false
        System.out.println(p1.greet());    // 输出:Hello, I'm Alice
    }
}

2. 关键特性

  1. 不可变性:所有字段为final,无Setter方法。
  2. 构造函数
    • 规范构造函数:参数与组件列表一致。
    • 紧凑构造函数:无需参数列表,直接校验或处理字段。
    • 非规范构造函数:必须调用其他构造函数(通过this())。
  3. 限制
    • 不能继承其他类,但可实现接口。
    • 所有非组件字段必须为static

3. 应用场景

  • DTO(数据传输对象):如API响应数据载体。
  • 值对象:如坐标点、日期范围等不可变数据。
  • 模式匹配:与instanceof结合简化类型判断。

三、密封类与记录类的对比

特性密封类(Sealed Classes)记录类(Record Classes)
设计目的限制继承关系,明确子类范围简化不可变数据类的定义
关键字sealed, permitsrecord
不可变性不强制(依赖子类实现)隐式不可变(字段为final
主要应用模式匹配、API设计数据载体、DTO
版本支持Java 17+Java 16+

四、进阶用法与最佳实践

1. 密封类结合记录类

// 密封类定义形状
public sealed interface Shape permits Circle, Rectangle {
    double area();
}

// 记录类实现密封接口
public record Circle(double radius) implements Shape {
    @Override public double area() { return Math.PI * radius * radius; }
}

public record Rectangle(double width, double height) implements Shape {
    @Override public double area() { return width * height; }
}

2. 模式匹配优化

// 结合密封类与模式匹配
public static void printArea(Shape shape) {
    if (shape instanceof Circle c) {
        System.out.println("Circle area: " + c.area());
    } else if (shape instanceof Rectangle r) {
        System.out.println("Rectangle area: " + r.area());
    }
}

3. 序列化支持

记录类可序列化(实现Serializable):

record GPS(double latitude, double longitude) implements Serializable {}

// 序列化与反序列化
GPS loc = new GPS(10, 20);
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("gps.obj"))) {
    oos.writeObject(loc);
}

五、总结

  • 密封类通过继承限制提升代码安全性,适用于需要明确子类范围的场景。
  • 记录类通过减少样板代码提升开发效率,适用于不可变数据建模。
  • 结合使用:两者可协同工作(如密封接口+记录实现),构建高表达力的领域模型。

参考资料

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值