一个密封类可以声明多少个子类?

tww*_*wwt 9 java java-17

密封类可以列出的子类的最大数量是多少(类似于接口):

public sealed class Foo permits A, B, C {
   // How many sub classes can  ^^^^^^^
   // be listed here?
}
Run Code Online (Sandbox Code Playgroud)

语言实际上是否定义了限制?即,在语言层面上它实际上是无限的吗?

如果语言层面没有这样的限制,那么似乎实现仍然必须有技术限制。某个地方应该有一个列表来存储允许的子类的某种表示形式。我希望那时使用 16 或 32 位整数。

Bri*_*etz 19

这里的答案是正确的,但我要补充一点,即使在 JVMS 4.7.31(PermittedSubtypes属性)中,您也找不到特定的限制。但由于每个允许的子类型都必须对应Constant_Class_info常量池中的a,而常量池限制为64K条目,并且每个Class常量都有一个关联String常量,所以无论如何你都不能获得超过32K的条目。当然,你的类中可能还有其他东西,它们会竞争常量池,所以你也不会得到它。但答案实际上是“数千”。

  • 至少,您需要类本身及其超类的“Constant_Class_info”(以及每个名称的条目)。然后是“PermissionSubclasses”属性名称本身的条目。因此,我们有 `(65534 - 5) / 2` 可能的类信息条目,实际上,我可以生成一个包含 32764 个允许的类(而不是更多)的接口。 (3认同)
  • 如果您的类没有声明任何成员,这只会为您赢得另一个类引用的空间,这显然会违反 JLS §4.3.2,并且如果没有构造函数,它就无法与任何子类一起很好地工作,更不用说要求了所有允许的子类必须位于同一模块内(即“java.base”),并且不能存在匿名子类。因此,密封“java.lang.Object”的类文件可能会被独立解析器接受,但无法在源代码级别或实际运行时环境中工作。相反,我生成的接口实际上可以加载到运行时中。 (2认同)

rzw*_*oot 12

JLS(Java 语言规范)通常不包含任何限制。尽管有很多限制。JVMS(Java 虚拟机规范)包含了限制。这是有道理的:其中许多限制从根本上与字节码和类文件格式概念相关,而这些概念是 JLS 不知道的 - 换句话说,即使 JLS 想要,它也不可能知道用 JLS 中定义的术语描述限制。

\n

例如,方法的最大大小是在字节码指令中“测量”的,这首先不是 Java 语言的概念。

\n

因此,JVMS 是寻找此类限制的地方。例如JVM 规范 \xc2\xa74.7.31(由 @akarnokd 提供,很好找到!)。

\n

有以下限制:

\n
    \n
  • 类型中的方法数量
  • \n
  • 类型中的字段数量
  • \n
  • 您的接口数量implements列表
  • \n
  • 方法可以具有的参数数量
  • \n
  • 方法“框架”的大小(需要多少堆栈空间)
  • \n
  • 本地槽数量的大小。最后两个项目符号或多或少地翻译成 java 语言,即对您可以拥有的本地变量数量的限制。
  • \n
  • 每个方法的字节码数。遇到此限制的最简单方法是将一个大块finally附加到带有大量块的尝试上catch。为所有这些块复制了finally 块。嵌套 try 块以实现指数级字节码增长!
  • \n
  • 签名中可以包含的类型参数的数量。
  • \n
  • 常量池中的条目数。这在 Java 语言中显示为对单个类中可以包含的文字数量的限制。
  • \n
\n

我确信我忘记了一些。

\n

还有一些未在规范中列出的限制;例如内存和堆大小限制,以及有关命令行开关的许多详细信息(例如,在一堆 JVM 版本和操作系统上,任何不能-Xss被单词整除的参数(设置堆栈大小))边界\',其定义取决于操作系统和体系结构,被完全忽略) - 全部未指定。

\n

其中一些是有意义的(关于您真正可以保留多少堆的确切细节取决于太多因素,无法详细记录),其中一些确实没有意义(事实上,工具开关的作用就像它们一样)高度规范,两者都有 2 层“较少规范”,-X并且-XX与 JVMS 和 JLS 都没有详细提及可用工具或其命令行开关的想法并没有很好地契合。

\n