Java 17 密封类(Sealed Classes)增强案例
密封类是Java 17正式引入的一个重要特性,它允许你控制哪些类可以继承或实现某个类/接口,让我通过几个实际案例来展示它的强大功能。

基础案例:形状计算系统
// 定义密封接口
public sealed interface Shape permits Circle, Rectangle, Triangle {
double area();
double perimeter();
}
// 圆形实现
public final class Circle implements Shape {
private final double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
public double area() {
return Math.PI * radius * radius;
}
@Override
public double perimeter() {
return 2 * Math.PI * radius;
}
public double getRadius() {
return radius;
}
}
// 矩形实现
public final class Rectangle implements 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;
}
@Override
public double perimeter() {
return 2 * (width + height);
}
public double getWidth() {
return width;
}
public double getHeight() {
return height;
}
}
// 三角形实现
public final class Triangle implements Shape {
private final double side1;
private final double side2;
private final double side3;
public Triangle(double side1, double side2, double side3) {
this.side1 = side1;
this.side2 = side2;
this.side3 = side3;
}
@Override
public double area() {
// 使用海伦公式
double s = (side1 + side2 + side3) / 2;
return Math.sqrt(s * (s - side1) * (s - side2) * (s - side3));
}
@Override
public double perimeter() {
return side1 + side2 + side3;
}
}
与模式匹配结合使用
// Java 17+ 模式匹配与密封类的完美结合
public class ShapeProcessor {
// 使用模式匹配处理不同形状
public static String describeShape(Shape shape) {
return switch (shape) {
case Circle c -> String.format("圆形,半径: %.2f,面积: %.2f",
c.getRadius(), c.area());
case Rectangle r -> String.format("矩形,宽: %.2f,高: %.2f,面积: %.2f",
r.getWidth(), r.getHeight(), r.area());
case Triangle t -> String.format("三角形,三边: %.2f, %.2f, %.2f,面积: %.2f",
t.getSide1(), t.getSide2(), t.getSide3(),
t.area());
};
}
// 验证形状是否合法
public static boolean isValidShape(Shape shape) {
return switch (shape) {
case Circle c -> c.getRadius() > 0;
case Rectangle r -> r.getWidth() > 0 && r.getHeight() > 0;
case Triangle t -> validTriangle(t.getSide1(), t.getSide2(), t.getSide3());
};
}
private static boolean validTriangle(double a, double b, double c) {
return a > 0 && b > 0 && c > 0 &&
(a + b > c) && (a + c > b) && (b + c > a);
}
}
简化中间类继承
// 使用non-sealed允许部分子类开放继承
public sealed class Vehicle permits Car, Truck, Motorcycle {
private final String brand;
private final String model;
public Vehicle(String brand, String model) {
this.brand = brand;
this.model = model;
}
public String getBrand() {
return brand;
}
public String getModel() {
return model;
}
public abstract double getMaxSpeed();
}
// 使用non-sealed允许进一步继承
public non-sealed class Car extends Vehicle {
private final int passengerCapacity;
public Car(String brand, String model, int passengerCapacity) {
super(brand, model);
this.passengerCapacity = passengerCapacity;
}
@Override
public double getMaxSpeed() {
return 250.0;
}
public int getPassengerCapacity() {
return passengerCapacity;
}
}
// 使用final表示最终类
public final class Truck extends Vehicle {
private final double loadCapacity;
public Truck(String brand, String model, double loadCapacity) {
super(brand, model);
this.loadCapacity = loadCapacity;
}
@Override
public double getMaxSpeed() {
return 120.0;
}
public double getLoadCapacity() {
return loadCapacity;
}
}
// 可以继续继承Car,因为它是non-sealed
public class SUV extends Car {
private final boolean fourWheelDrive;
public SUV(String brand, String model, int passengerCapacity, boolean fourWheelDrive) {
super(brand, model, passengerCapacity);
this.fourWheelDrive = fourWheelDrive;
}
@Override
public double getMaxSpeed() {
return 200.0;
}
public boolean isFourWheelDrive() {
return fourWheelDrive;
}
}
实际业务场景:支付系统
// 支付系统示例
public sealed interface PaymentMethod permits CreditCard, DebitCard, CryptoWallet {
String getProvider();
double processPayment(double amount);
}
// 信用卡实现
public final class CreditCard implements PaymentMethod {
private final String cardNumber;
private final String expiryDate;
public CreditCard(String cardNumber, String expiryDate) {
this.cardNumber = cardNumber;
this.expiryDate = expiryDate;
}
@Override
public String getProvider() {
return "Visa/MasterCard";
}
@Override
public double processPayment(double amount) {
// 信用卡支付逻辑
double fee = amount * 0.02; // 2%手续费
return amount + fee;
}
public String getCardNumber() {
return cardNumber;
}
}
// 借记卡实现
public final class DebitCard implements PaymentMethod {
private final String bankName;
private final String accountNumber;
public DebitCard(String bankName, String accountNumber) {
this.bankName = bankName;
this.accountNumber = accountNumber;
}
@Override
public String getProvider() {
return bankName;
}
@Override
public double processPayment(double amount) {
// 借记卡支付逻辑
return amount; // 无额外手续费
}
public String getBankName() {
return bankName;
}
}
// 加密货币钱包
public final class CryptoWallet implements PaymentMethod {
private final String walletAddress;
private final String currency;
public CryptoWallet(String walletAddress, String currency) {
this.walletAddress = walletAddress;
this.currency = currency;
}
@Override
public String getProvider() {
return "Crypto";
}
@Override
public double processPayment(double amount) {
// 加密货币支付逻辑
double fee = amount * 0.001; // 0.1%手续费
return amount + fee;
}
public String getWalletAddress() {
return walletAddress;
}
}
// 支付处理器
public class PaymentProcessor {
public static String processPayment(PaymentMethod method, double amount) {
return switch (method) {
case CreditCard cc -> String.format(
"信用卡支付: 金额=%.2f, 手续费=%.2f, 总计=%.2f, 卡号最后4位=%s",
amount, method.processPayment(amount) - amount,
method.processPayment(amount),
cc.getCardNumber().substring(cc.getCardNumber().length() - 4));
case DebitCard dc -> String.format(
"借记卡支付: 金额=%.2f, 手续费=0.00, 总计=%.2f, 银行=%s",
amount, method.processPayment(amount), dc.getBankName());
case CryptoWallet cw -> String.format(
"加密货币支付: 金额=%.2f, 手续费=%.2f, 总计=%.2f, 币种=%s",
amount, method.processPayment(amount) - amount,
method.processPayment(amount), cw.getCurrency());
};
}
}
测试代码
public class SealedClassDemo {
public static void main(String[] args) {
// 测试形状系统
System.out.println("=== 形状系统测试 ===");
Shape circle = new Circle(5);
Shape rectangle = new Rectangle(4, 6);
Shape triangle = new Triangle(3, 4, 5);
System.out.println(ShapeProcessor.describeShape(circle));
System.out.println(ShapeProcessor.describeShape(rectangle));
System.out.println(ShapeProcessor.describeShape(triangle));
// 测试支付系统
System.out.println("\n=== 支付系统测试 ===");
PaymentMethod creditCard = new CreditCard("1234-5678-9012-3456", "12/25");
PaymentMethod debitCard = new DebitCard("中国工商银行", "6222021234567890");
PaymentMethod cryptoWallet = new CryptoWallet("0x1234...", "ETH");
System.out.println(PaymentProcessor.processPayment(creditCard, 1000));
System.out.println(PaymentProcessor.processPayment(debitCard, 500));
System.out.println(PaymentProcessor.processPayment(cryptoWallet, 800));
}
}
输出结果
=== 形状系统测试 ===
圆形,半径: 5.00,面积: 78.54
矩形,宽: 4.00,高: 6.00,面积: 24.00
三角形,三边: 3.00, 4.00, 5.00,面积: 6.00
=== 支付系统测试 ===
信用卡支付: 金额=1000.00, 手续费=20.00, 总计=1020.00, 卡号最后4位=3456
借记卡支付: 金额=500.00, 手续费=0.00, 总计=500.00, 银行=中国工商银行
加密货币支付: 金额=800.00, 手续费=0.80, 总计=800.80, 币种=ETH
密封类的关键优势
- 代码安全性:明确限制继承关系,防止意外扩展
- 模式匹配完备性:编译器知道所有子类型,switch表达式不需要default分支
- API设计清晰:明确表达类层次结构的完整性和封闭性
- 更好的类型安全性:配合模式匹配,减少类型转换错误
- 可维护性:代码结构更清晰,易于理解和维护
密封类是Java 17中一个非常实用的特性,特别适合用于领域模型设计、状态机实现和API设计等场景。