Java中枚举元素的最大数量
Java 枚举中允许的最大元素数量是多少?
我想找出 switch 语句中的最大案例数。由于 switch 中允许的最大原始类型是 int,因此我们有从 -2,147,483,648 到 2,147,483,647 的情况以及一种默认情况。然而枚举也是允许的......所以问题......
What is the maximum number of elements allowed in an enum in Java?
I wanted to find out the maximum number of cases in a switch statement. Since the largest primitive type allowed in switch is int, we have cases from -2,147,483,648 to 2,147,483,647 and one default case. However enums are also allowed... so the question..
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
来自 类文件格式规范:
我相信这意味着在一个类中不能有超过 65535 个名为“things”的东西,这也会限制枚举常量的数量。
幸运的是,这不会发生:
From the class file format spec:
I believe that this implies that you cannot have more then 65535 named "things" in a single class, which would also limit the number of enum constants.
Fortunately, that cannot happen:
枚举元素的最大数量是 2746。阅读规范非常具有误导性,导致我创建了一个有缺陷的设计,并假设我永远不会达到 64K 甚至 32K 高水位线。不幸的是,这个数字比规格显示的要低得多。作为测试,我在 Java 7 和 Java 8 上尝试了以下操作:运行以下代码,将其重定向到文件,然后编译生成的 .java 文件。
结果,2746 有效,2747 无效。
在 2746 个条目之后,编译器会抛出代码太大错误,例如
反编译此 Enum 类文件,限制似乎是由静态构造函数中为每个枚举值生成的代码(大部分)引起的。
The maximum number of enum elements is 2746. Reading the spec was very misleading and caused me to create a flawed design with the assumption I would never hit the 64K or even 32K high-water mark. Unfortunately, the number is much lower than the spec seems to indicate. As a test, I tried the following with both Java 7 and Java 8: Ran the following code redirecting it to a file, then compiled the resulting .java file.
Result, 2746 works, and 2747 does not.
After 2746 entries, the compiler throws a code too large error, like
Decompiling this Enum class file, the restriction appears to be caused by the code generated for each enum value in the static constructor (mostly).
枚举肯定有限制,主要(硬)限制约为 32K 值。它们受到 Java 类最大值的限制,包括“常量池”(64K 条目)以及(在某些编译器版本中)静态初始化程序上的方法大小限制(64K 字节码)。
“Enum”内部初始化,每个值使用两个常量——一个 FieldRef 和一个 Utf8 字符串。这给出了 ~32K 值的“硬限制”。
较旧的编译器(至少是 Eclipse Indigo)也会遇到静态初始化方法大小的问题。实例化每个值和需要 24 个字节的字节码将其添加到值数组中。可能会遇到 2730 个值左右的限制。
较新的编译器(至少 JDK 7)会自动将大型静态初始化程序拆分为名为
" enumconstinitialization$2"
、"enumconstinitialization$3"
等的方法,因此不受第二个限制。您可以通过 javap -v -c YourEnum.class 反汇编字节码,看看它是如何工作的。
[理论上可以将“旧式”Enum 类编写为手工编码的 Java,以打破 32K 限制并接近 64K 值。该方法是通过反射来初始化枚举值,以避免池中需要字符串常量。我测试了这种方法,它在 Java 7 中有效,但这种方法的可取性(安全问题)值得怀疑。]
编辑注意:Utf8 是 Java 类文件 IIRC 中的内部类型,这不是一个拼写错误已更正。
Enums definitely have limits, with the primary (hard) limit around 32K values. They are subject to Java class maximums, both of the 'constant pool' (64K entries) and -- in some compiler versions -- to a method size limit (64K bytecode) on the static initializer.
'Enum' initialization internally, uses two constants per value -- a FieldRef and a Utf8 string. This gives the "hard limit" at ~32K values.
Older compilers (Eclipse Indigo at least) also run into an issue as to the static initializer method-size. With 24 bytes of bytecode required to instantiate each value & add it to the values array. a limit around 2730 values may be encountered.
Newer compilers (JDK 7 at least) automatically split large static initializers off into methods named
" enum constant initialization$2"
," enum constant initialization$3"
etc so are not subject to the second limit.You can disassemble bytecode via
javap -v -c YourEnum.class
to see how this works.[It might be theoretically possible to write an "old-style" Enum class as handcoded Java, to break the 32K limit and approach close to 64K values. The approach would be to initialize the enum values by reflection to avoid needing string constants in the pool. I tested this approach and it works in Java 7, but the desirability of such an approach (safety issues) are questionable.]
Note to editors: Utf8 was an internal type in the Java classfile IIRC, it's not a typo to be corrected.
Java 15+ 的更新
在 JDK 15 中,枚举中常量的最大数量提高到约 4103: https://bugs.openjdk.java.net/browse/JDK-8241798
这是通过将静态初始化器分为两部分来实现的:
Java 15 之前(伪代码):
自 Java 15 以来:
这允许静态初始化器包含更多代码(直到达到 64 KB 限制),从而初始化更多枚举常量。
Update for Java 15+
In JDK 15, the maximal number of constants in enums was raised to about 4103: https://bugs.openjdk.java.net/browse/JDK-8241798
This was achieved by splitting the static initializer into two parts:
Before Java 15 (pseudocode):
Since Java 15:
This allowed the static initializer to contain more code (until it hits the 64 kilobytes limit) and therefore to initialize more enum constants.
好吧,在 jdk1.6 上我就达到了这个限制。有人在 xsd 中有 10,000 个枚举,当我们生成时,我们得到一个 60,000 行枚举文件,我得到一个很好的 java 编译器错误
[错误] 无法执行目标 org.apache.maven.plugins:maven-compiler-plugin:2.0 .2:在项目框架上编译(默认编译):编译失败
[错误] /Users/dhiller/Space/ifp-core/framework/target/ generated-sources/com/framework/util/LanguageCodeSimpleType.java:[7627,4] 代码太大,
因此很可能限制远低于这里的其他答案或者可能生成的评论等占用了太多空间。请注意,java 编译器错误中的行号是 7627,但如果行限制是 7627,我想知道行长度限制是多少;)这可能是相似的。 IE。限制可能不是基于枚举数,而是基于行长度限制或文件中的行数限制,因此您可以将枚举重命名为 A、B 等,使其非常小,以便将更多枚举放入枚举中。
我不敢相信有人写了一个带有 10,000 枚举的 xsd..他们一定生成了 xsd 的这一部分。
Well, on jdk1.6 I hit this limit. Someone has 10,000 enum in an xsd and when we generate, we get a 60,000 line enum file and I get a nice java compiler error of
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:2.0.2:compile (default-compile) on project framework: Compilation failure
[ERROR] /Users/dhiller/Space/ifp-core/framework/target/generated-sources/com/framework/util/LanguageCodeSimpleType.java:[7627,4] code too large
so quite possibly the limit is much lower than the other answers here OR maybe the comments and such that are generated are taking up too much space. Notice the line number is 7627 in the java compiler error though if the line limit is 7627, I wonder what the line length limit is ;) which may be similar. ie. the limits may be not be based on number of enums but line length limits or number of lines in the file limit so you would have rename enums to A, B, etc. to be very small to fit more enums into the enum.
I can't believe someone wrote an xsd with a 10,000 enum..they must have generated this portion of the xsd.
Java 中任何方法的最大大小为 65536 字节。虽然理论上您可以拥有较大的开关或更多的枚举值,但它是您可能首先使用的方法的最大大小。
The maximum size of any method in Java is 65536 bytes. While you can theoretically have a large switch or more enum values, its the maximum size of a method you are likely to hit first.
Enum
类使用int
来跟踪每个值的序数,因此最大值最多与 int 相同(如果不是低很多的话)。正如其他人所说,如果你必须问你就做错了
The
Enum
class uses anint
to track each value's ordinal, so the max would be the same as int at best, if not much lower.And as others have said, if you have to ask you're Doing It Wrong
出于任何实际目的,本身没有最大数量。如果您需要在一个类中定义数千个枚举,则需要重写您的程序。
There is no maximum number per se for any practical purposes. If you need to define thousands of enums in one class you need to rewrite your program.