Java密封类是从Java 15开始引入的预览特性,核心作用是限制哪些类可以继承或实现当前类,避免类被无限制扩展,提升代码的安全性和可维护性。该特性在Java 15、16中作为预览功能存在,到Java 17时正式成为标准特性,语法上也有细微调整。

Java 15/16预览版本的密封类定义语法
在预览版本中,定义密封类需要使用sealed关键字,同时必须配合permits子句明确指定允许继承的子类,并且需要开启预览特性编译。密封类本身需要用abstract修饰如果是抽象类,或者作为普通类声明。
预览版本的定义示例:
// 抽象密封类,指定允许继承的子类为Cat和Dog
public abstract sealed class Animal permits Cat, Dog {
public abstract void eat();
}
// 允许的子类,需要用non-sealed或者final修饰
public final class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
public non-sealed class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗吃骨头");
}
}
注意预览版本编译时需要添加--enable-preview参数,运行时也需要对应参数,否则会报语法错误。
Java 17正式版本的密封类定义语法
Java 17中密封类成为正式特性,不再需要开启预览参数,语法规则基本保持一致,但简化了部分校验逻辑,同时支持密封接口的定义。
密封类的定义规则
- 使用
sealed修饰类,位于class关键字之前 - 必须添加
permits子句,列出所有允许直接继承的子类,子类必须和密封类在同一个模块中(如果是模块化的项目),或者同一个包中(非模块化项目) - 所有允许的子类必须使用
final、sealed或者non-sealed三者之一修饰,不能使用普通的extends继承密封类
正式版本的密封类示例代码:
// 正式版本密封类,无需预览参数
public sealed class Shape permits Circle, Rectangle, Triangle {
private final String name;
public Shape(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
// final子类,不允许再被继承
public final class Circle extends Shape {
private final double radius;
public Circle(double radius) {
super("圆形");
this.radius = radius;
}
public double getRadius() {
return radius;
}
}
// non-sealed子类,允许继续被继承
public non-sealed class Rectangle extends Shape {
private final double length;
private final double width;
public Rectangle(double length, double width) {
super("长方形");
this.length = length;
this.width = width;
}
}
// sealed子类,继续限制继承范围
public sealed class Triangle extends Shape permits RightTriangle {
private final double sideA;
private final double sideB;
private final double sideC;
public Triangle(double sideA, double sideB, double sideC) {
super("三角形");
this.sideA = sideA;
this.sideB = sideB;
this.sideC = sideC;
}
}
public final class RightTriangle extends Triangle {
public RightTriangle(double sideA, double sideB) {
super(sideA, sideB, Math.sqrt(sideA * sideA + sideB * sideB));
}
}
密封接口的定义语法
Java 17正式版本也支持密封接口,规则与密封类类似,使用sealed修饰接口,配合permits指定允许实现该接口的类或接口。
// 密封接口,允许实现类为Bird和Fish
public sealed interface Flyable permits Bird, Fish {
void fly();
}
public final class Bird implements Flyable {
@Override
public void fly() {
System.out.println("鸟用翅膀飞");
}
}
public non-sealed class Fish implements Flyable {
@Override
public void fly() {
System.out.println("飞鱼跃出水面滑翔");
}
}
版本差异总结
| 对比项 | Java 15/16预览版本 | Java 17正式版本 |
|---|---|---|
| 是否需开启预览参数 | 是,编译运行都需要--enable-preview | 否,默认支持 |
| 密封接口支持 | 不支持 | 支持 |
| 语法校验严格度 | 校验更严格,部分场景会额外报错 | 校验逻辑优化,更符合开发习惯 |
如果项目使用的是Java 17及以上版本,建议直接使用正式语法,无需额外配置参数,同时可以结合密封接口使用,更灵活地控制继承体系。
sealed_classJava_15Java_17密封类语法修改时间:2026-07-19 10:45:13