Java 15中密封类特性中,final和非密封类有什么区别?

15

我有以下封装接口(Java 15):

public sealed interface Animal permits Cat, Duck {

    String makeSound();
}

这个接口被2个类实现:

public final class Cat implements Animal {

    @Override
    public String makeSound() {
        return "miau";
    }
}

public non-sealed class Duck implements Animal {

    @Override
    public String makeSound() {
        return "quack";
    }
}

有人能告诉我finalnon-sealed之间的区别吗?final阻止我创建其他子类,但是non-sealedDuck应用了什么行为?


2
一个允许的子类可以被声明为非密封的,以便其层次结构的部分恢复为对未知子类的扩展是开放的。(密封类无法阻止其允许的子类这样做。) - Youcef LAIDANI
3
一个final类永远不能被子类化(旧功能)。一个non-sealed类是特别开放一个类来被子类化的,当它的基类是sealed时需要这样做。 - Andreas
2
密封是终结的一般化;一个终态类不能被任何东西扩展,一个密封类通过明确列出允许的子类型来扩展。(一个终态类就像一个没有允许列表的密封类。)其他语言采用了一种方法,即密封类型的允许子类型可以任意扩展,但这经常会令人感到惊讶并导致错误。因此,Java要求您明确说明:对于密封类型的子类型,您必须选择一个选项:final、sealed或open for extension。(记录是隐式地终态的,因此您不必明确说明它。) - Brian Goetz
3个回答

19
  • 由于您将Cat标记为final,因此没有其他类可以扩展Cat
  • 由于您将Duck标记为non-sealed,因此任何类都可以扩展Duck

当将一个类标记为sealed时,所有直接扩展的类(在permits子句之后的类)必须被标记为finalsealednon-sealed

  • 将一个扩展了sealed类的类标记为sealed,会对其产生相同的影响:只有在permits子句指定的类才允许扩展它。

  • non-sealed只是“打破封印”,所以不必在层次结构中继续执行。扩展的类重新开放,可以被未知的子类扩展。

  • final实际上与在permits子句后面没有指定任何类的sealed相同。请注意,不能在permits后面不指定任何内容,因此sealed无法替换final


谢谢,现在很清楚了。每个类都可以从一个“非密封”类继承 :) - Michael Kemmerzell

3

final和非sealed类有一些区别。

final类:你不能继承这个类。我的意思是你不能将这个类扩展到其他类中。

非sealed类:你可以从其他类继承这个类。

例如:
这个被封闭的接口只允许Cat和Duck类使用。请注意,Cat和Duck必须是final、非sealed或者sealed类。

public sealed interface Animal permits Cat, Duck {
  String makeSound();
}

现在,我正在创建Cat & Duck类。其中Cat是最终类,而另一个是非密封类。

public final class Cat implements Animal {

    @Override
    public String makeSound() {
        return "miau";
    }
}

public non-sealed class Duck implements Animal {

    @Override
    public String makeSound() {
        return "quack";
    }
}

如果您尝试继承Cat类,则会出现编译错误,因为Cat类是final的,无法继承。另一方面,Duck类是可扩展的,因为它是非密封类。

//Got Error
public class MyCat extends Cat {

 .......
}

//Error not show.Duck class is extendable
public class MyDuck extends Duck {

    .....
}

0
一个final类没有子类,这意味着没有其他类可以扩展它。 任何类都可以扩展非sealed类。
当您将类标记为sealed时,只有允许的子类可以扩展它,并且只能具有这些修饰符final、sealed或non-sealed:
public sealed class NumberSystem
    // The permits clause has been omitted
    // as all the subclasses exists in the same file.
{ }
non-sealed class Decimal extends NumberSystem { .. }
final class NonRecurringDecimal extends Decimal {..}
final class RecurringDecimal extends Decimal {..}

尽管NumberSystem根级别层次结构关闭为已知类集,但您可以使用非密封关键字允许子层次结构开放。

密封和非密封的组合允许您限制层次结构的部分内容,但不是全部。

在下面的图表中,我们将密封类NumberSystem的根层次结构限制为已知的一组子类。然而,非密封 Decimal类允许任何未知的子类(例如RecurringDecimal)扩展它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接