Java 17 中有哪些密封类?

今天,我将Java版本从16更新到17,我发现类是其中的新功能。我认为它可以这样声明:sealed

public sealed class Main permits AClass, AnotherClass {
}

但是,密封类在Java中的用途是什么?

我也知道这是jdk-15中的预览功能。


答案 1

您可以点击此链接查看示例。

简而言之,密封类使您可以控制哪些模型,类等可以实现或扩展该类/接口。

链接中的示例:

public sealed interface Service permits Car, Truck {

    int getMaxServiceIntervalInMonths();

    default int getMaxDistanceBetweenServicesInKilometers() {
    return 100000;
  }
}

此接口仅允许汽车和卡车实现它。


答案 2

JEP 409将其解释为

密封的类或接口只能由允许扩展或实现的类和接口来实现。

更实际的解释如下:

过去的情况是:

  • 您无法限制一个接口由另一个接口扩展
  • 您无法限制哪些类能够实现特定接口。
  • 您必须将一个类声明为 final,以免被另一个类扩展。这样,任何类都无法扩展声明的最终类。这是非黑即白的方法。

密封关键字的现状是:

  • 现在,您可以限制由其他接口扩展的接口,并仅为允许扩展它的某些特定接口制定规则。

    例:

    public sealed interface MotherInterface permits ChildInterfacePermitted {}
    
    //Has to be declared either as sealed or non-sealed
    public non-sealed interface ChildInterfacePermitted extends MotherInterface {}  
    
    public interface AnotherChildInterface extends MotherInterface {} 
    //compiler error! It is not included in the permits of mother inteface
    
  • 现在,您可以创建一个接口,并仅选择允许实现该接口的特定类。不允许所有其他类实现它。

    例:

     public sealed interface MotherInterface permits ImplementationClass1 {} 
    
     //Has to be declared either as final or as sealed or as non-sealed
     public final class ImplementationClass1 implements MotherInterface {} 
    
     public class ImplementationClass2 implements MotherInterface {} 
     //compiler error! It is not included in the permits of mother inteface
    
  • 现在,您可以限制要扩展的类(与之前使用 final 相同),但现在可以允许某些特定类对其进行扩展。因此,现在您拥有了更多的控制权,就像在关键字 final 绝对限制每个类扩展声明的最终类之前一样

    例:

    public sealed class MotherClass permits ChildClass1 {}
    
    //Has to be declared either as final or as sealed or as non-sealed
    public non-sealed class ChildClass1 extends MotherClass {} 
    
     public class ChildClass2 extends MotherClass {} 
     //compiler error! It is not included in the permits of MotherClass
    

重要提示:

  • 密封类及其允许的子类必须属于同一模块,如果是在未命名模块中声明的,则必须属于同一包。

    例:

    假设我们有相同的未命名模块和以下包

      -packageA
         -Implementationclass1.java
      -packageB
         -MotherClass.java
    

       -root
          -MotherClass.java
          -packageA
             -Implementationclass1.java
    

    你会得到错误 类不允许从另一个包扩展密封类。因此,如果你有一个未命名的模块,密封函数的所有参与类和接口必须完全放在同一个包上。

  • 每个允许的子类必须直接扩展密封类。