密封类(Sealed Classes)

通过在类定义前面放置关键字 sealed,可以将类声明为密封类。同时使用关键字 permits 来限制哪些类可以继承或实现该密封类。在下面的示例中,声明了密封类 BasePosition,并且只允许类 PointGuard 和类 ShootingGuard 可以继承该密封类。

1
2
3
public sealed class BasePosition permits PointGuard, ShootingGuard {
// Class members here.
}

关键字 sealed 除了可以修饰类外,还可以用来修饰接口,只允许哪些类可以实现该接口。例如:

1
2
3
public sealed interface UserService permits UserServiceImpl {
// Some methods here.
}

如果定义的密封类继承了父类,或实现了其他接口,那么关键字 permits 需要放在关键字 extendsimplements 的后面。在下面的示例中,密封类 Felidae 继承了抽象类 Animal,并实现了 BaseAction 接口,只允许类 Lion 可以继承该密封类。

1
2
3
public sealed class Felidae extends Animal implements BaseAction permits Lion {
// Some methods here.
}

密封类的子类

根据密封性的传递要求,密封类的子类必须被关键字 sealednon-sealedfinal 中的一个所修饰:

  • sealed:继续延续密封类特性,继续指定继承的类;
  • non-sealed:声明这个类为非密封类,可以被任意继承;
  • final:不允许继承。

例如,将子类 Lion 继续声明为密封类:

1
2
3
public sealed class Lion extends Felidae permits LionBaby {
// Class members here.
}

将子类 Lion 声明为非密封类:

1
2
3
public non-sealed class Lion extends Felidae {
// Class members here.
}

将子类 Lion 定义为不允许被其他类继承:

1
2
3
public final class Lion extends Felidae {
// Class members here.
}

小结

密封类(Sealed Classes)这一特性首次出现是在 Java15 的 JEP 360 中,并在 Java 16 的 JEP 397 中进行了增强,最终在 Java 17 这个长期支持的版本中成为正式的新特性(JEP 409)。密封类的作用是限制类的继承或接口的实现,只允许特定的类可以继承或实现。

与密封类相关的主要关键字有 sealednon-sealedpermits,它们的作用分别如下:

  • sealed:修饰类/接口,用来描述这个类/接口为密封类/接口
  • non-sealed:修饰类/接口,用来描述这个类/接口为非密封类/接口
  • permits:用在extendsimplements之后,指定可以继承或实现的类

(END)