Java 教程

Java 控制语句

面向对象编程

Java 内置类

Java 文件处理

Java 错误和异常

Java 多线程

Java 同步

Java 网络

Java 集合

Java 接口

Java 数据结构

Java 集合算法

高级 Java

Java 杂项

Java API 和框架

Java 类引用

Java 有用资源

Java - 密封类和接口



Java 15 引入了一个密封类作为预览功能,它提供了对继承的细粒度控制。Java 16 提供了一些小的增强功能,并将此功能保留为预览。随着 Java 17 的发布,密封类和接口成为了标准特性。密封类/接口功能添加到 Java 中,为开发人员提供了对继承的细粒度控制。密封类可以定义允许扩展它的子类型,而其他类则不能扩展它。

以下是需要考虑的密封类的要点:

  • 密封类使用 sealed 关键字声明。
  • 密封类允许使用 permits 关键字声明哪些类可以是子类型。
  • 扩展密封类的类必须声明为 sealed、non-sealed 或 final。
  • 密封类有助于在继承中创建有限且可确定的类层次结构。

密封接口

一个接口可以使用 sealed 关键字标记为密封接口,然后使用permits关键字,我们可以添加可以扩展此接口的接口。

public sealed interface Person permits Employee, Manager {
}

密封接口示例

在此示例中,我们创建了一个密封接口 Person,它允许 Employee 和 Manager 接口扩展它。Employee 和 Manager 接口具有不同的方法来获取人员的 ID。现在,为了获取人员的 ID,我们使用 instanceof 运算符检查实例是否为 Employee 或 Manager 并获取相应的 ID。因此,我们可以看到,预先知道允许的接口有助于在这种情况下进行开发。

package com.tutorialspoint;

public class Tester {
   public static void main(String[] args) {
      // create an instance of Manager
      Person manager = new CorpManager(23, "Robert");

      // get the id
      System.out.println("Id: " + getId(manager));
   }
   public static int getId(Person person) {
      // check if person is employee then return employee id
      if (person instanceof Employee) {
         return ((Employee) person).getEmployeeId();
      } 
      // if person is manager then return manager id
      else if (person instanceof Manager) {
         return ((Manager) person).getManagerId();
      }
      return -1;
   }
}

// a sealed interface Person which is to be inherited by Employee
// and Manager interfaces
sealed interface Person permits Employee, Manager {
   String getName();
}

// Employee and Manager interfaces have to extend Person and can be sealed or non-sealed
non-sealed interface Employee extends Person {
   int getEmployeeId();
}

non-sealed interface Manager extends Person {
   int getManagerId();
}

class CorpEmployee implements Employee {
   String name;
   int id;

   public CorpEmployee(int id,String name) {
      this.name = name;
      this.id = id;
   }

   public String getName() {
      return name;
   }

   public int getEmployeeId() {
      return id;
   }		
}

class CorpManager implements Manager {
   String name;
   int id;
   public CorpManager(int id,String name) {
      this.name = name;
      this.id = id;
   }
   public String getName() {
      return name;
   }

   public int getManagerId() {
      return id;
   }		
}

让我们编译并运行上述程序,这将产生以下结果:

Id: 23

密封类

与密封接口类似,也可以使用sealed关键字标记为密封类,然后使用 permits 关键字,我们可以添加可以扩展此类的子类。

public abstract sealed class Person permits Employee, Manager {
}

子类需要具有 sealed/final 或 non-sealed 修饰符。

public final class Manager extends Person {
}

具有 non-sealed 修饰符的子类对所有类开放以进行扩展。

public non-sealed class Employee extends Person {
}

约束

在扩展密封类时,我们应该注意使用密封类的一些约束。

  • 允许的子类应与密封类位于同一模块中。

  • 允许的子类必须扩展密封类。

  • 允许的子类必须使用 final、sealed 或 non-sealed 修饰符之一。

密封类示例

在此示例中,我们创建了一个密封抽象类 Person,它允许 Employee 和 Manager 类扩展它。Employee 和 Manager 类具有不同的方法来获取人员的 ID。现在,为了获取人员的 ID,我们使用 instanceof 运算符检查实例是否为 Employee 或 Manager 并获取相应的 ID。因此,我们可以看到,预先知道允许的子类有助于在这种情况下进行开发。

package com.tutorialspoint;

public class Tester {
   public static void main(String[] args) {
      // create an instance of Manager
      Person manager = new Manager(23, "Robert");

      // get the id
      System.out.println("Id: " + getId(manager));
   }
   public static int getId(Person person) {
      // check if person is employee then return employee id
      if (person instanceof Employee) {
         return ((Employee) person).getEmployeeId();
      } 
      // if person is manager then return manager id
      else if (person instanceof Manager) {
         return ((Manager) person).getManagerId();
      }
      return -1;
   }
}

// a sealed class Person which is to be inherited by Employee
// and Manager classes
abstract sealed class Person permits Employee, Manager {
   String name;
   String getName() {
      return name;
   }
}

// Employee class has to extend Person and should have a modifier
final class Employee extends Person {
   String name;
   int id;
   Employee(int id, String name){
      this.id = id;
      this.name = name;
   }
   int getEmployeeId() {
      return id;
   }
}

// We can mark a sub-class as non-sealed, so that it can be extended if required
non-sealed class Manager extends Person {
   int id;
   Manager(int id, String name){
      this.id = id;
      this.name = name;
   }
   int getManagerId() {
      return id;
   }
}

让我们编译并运行上述程序,这将产生以下结果:

Id: 23
广告