一篇学会 Java SE 17 密封类

Java引入了密封类特性,允许开发者限制哪些类能继承特定的类或接口,增强了类型系统的安全性。密封类通过sealed修饰符声明,并用permits指定可继承的子类。非密封类则不受此限制,可以被任意类继承。这一特性在JavaSE15中预览,并在JavaSE17中成为永久特性。
摘要由CSDN通过智能技术生成

密封类在 Java SE 15 中首次预览,此功能在 Java SE 17 版本中是永久性的。这意味着它可以在为 Java SE 17 编译的任何程序中使用,而无需启用预览功能。

密封类

你定义了一个 Person 类,但是有只 Dog 想继承这个 Person 类,这还得了?狗子就是狗子,怎么能有人的行为捏?这只狗子想干嘛!要成精不成,妖孽还不现出原型!对于狗子想要继承人行为的这种做法必须达咩,身为人类的我们必须阻止这种行为!!!

1. 声明密封类

通过密封一个类,可以指定允许哪些类扩展它,并防止任何其他任意类这样做想,这就需要用到 sealed 修饰符去修饰这个类为密封类,然后需要在类名后边使用 permits 子句去指定可以扩展的子类。请看如下代码:

Person:人类

public sealed class Person permits Worker {  
  
    // 姓名  
    String name;  

    // 年龄  
    int age;  

    // 母语  
    String motherTongue;  
  
}

Worker:工人

public sealed class Worker extends Person permits Cleaner, Programmer {  
  
    // 职业  
    String profession;  

    // 工资  
    double money;  

    // 工作地  
    String workGround;  
  
}

Programmer:程序员

public final class Programmer extends Worker {  
  
    // 语言  
    String language;  

    // 键盘  
    String keyboard;  
  
}

看到上边这三段代码,能不能注意到什么?

  1. sealed 不仅仅可以修饰父类,也可以修饰子类,子类也是可以有子类的。就像爷爷、爸爸与你的关系。
  2. 子类使用 permits 子句前一定要先继承他的父类,否则会报错,除非他仅仅当一个父类。
  3. 当一个类仅作为子类继承 sealed 修饰的父类时,子类必须使用 final 修饰为最终类。
  4. 子类必须在编译时可由父类访问,说人话就是,子类存在才行。
  5. permits 是必须存在的,且必须指定子类。

墨菲定律告诉我们:“你越害怕发生的事,越会发生”。既然有密封类,就要有非密封类,因为你不知道事情发展的方向,请看如下代码:

Cleaner:清洁工

public non-sealed class Cleaner extends Worker {  
  
    // 工种  
    String typeOfWork;  
  
}

StreetCleaner:马路清洁工

public class StreetCleaner extends Cleaner {  
  
}

Cleaner 类中 使用 non-sealed 修饰符来修饰这个类为非密封类,你不需要在非密封类中使用 permits 指定子类,因为他可以被任何类所继承,就像 StreetCleaner 类继承 StreetCleaner一样,而且你不需要将这个子类修饰为 final 的。

Person:人类

public sealed class Person {  
  
    // 姓名  
    String name;  

    // 年龄  
    int age;  

    // 母语  
    String motherTongue;  
  
}



sealed class Worker extends Person {  
  
    // 职业  
    String profession;  

    // 工资  
    double money;  

    // 工作地  
    String workGround;  
  
}



non-sealed class Cleaner extends Worker {  
  
    // 工种  
    String typeOfWork;  
  
}



class StreetCleaner extends Cleaner {  
  
}



final class Programmer extends Worker {  
  
    // 语言  
    String language;  

    // 键盘  
    String keyboard;  
  
}

在上边代码中,如果你将之前的所有类都放在与密封类相同的文件中,那么使用 sealed 修饰的类 就不需要使用 permits 指定子类。

注意:

子类想要继承密封类必须与密封类位于同一包中

2. 声明密封接口

与密封类一样,要密封接口,需要使用 sealed 修饰符修饰接口。然后添加 permits 子句,它指定可以实现密封接口的类以及可以扩展密封接口的接口。

下面请看 Oracle 官网的一个案例:

Expressions:表达式


public class Expressions {  
    public static void main(String[] args) {  
        System.out.println(  
        new TimesExpr(new PlusExpr(new ConstantExpr(6), new ConstantExpr(7)),  
        new NegExpr(new ConstantExpr(8))).eval());  
        }  
}  
  
  
 
sealed interface Expr permits ConstantExpr, PlusExpr, TimesExpr, NegExpr {  
    public int eval();  
}  


  
final class ConstantExpr implements Expr {  
    int i;  
  
    ConstantExpr(int i) {  
        this.i = i;  
    }  
  
    @Override  
    public int eval() {  
        return i;  
    }  
}  
  
  
  
final class PlusExpr implements Expr {  
    Expr a, b;  
  
    PlusExpr(Expr a, Expr b) {  
        this.a = a;  
        this.b = b;  
    }  
  
    @Override  
    public int eval() {  
        return a.eval() * b.eval();  
    }  
}  
  
  
  
final class TimesExpr implements Expr {  
    Expr a, b;  
  
    TimesExpr(Expr a, Expr b) {  
        this.a = a;  
        this.b = b;  
    }  
  
    @Override  
    public int eval() {  
        return a.eval() * b.eval();  
    }  
}  
 
 
 
final class NegExpr implements Expr {  
    Expr e;  
  
    NegExpr(Expr e) {  
        this.e = e;  
    }  
  
    @Override  
    public int eval() {  
        return -e.eval();  
    }  
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值