Java中的最大枚举元素数

时间:2010-12-17 06:56:59

标签: java enums switch-statement

Java中枚举中允许的最大元素数是多少?

我想找出switch语句中的最大个案数。由于switch中允许的最大基本类型是int,因此我们有-2,147,483,648到2,147,483,647的情况和一个默认情况。但是也允许枚举...所以问题..

8 个答案:

答案 0 :(得分:29)

来自class file format spec

  

ClassFile结构的16位constant_pool_count字段(第4.1节)将每类或每接口常量池限制为65535个条目。这是对单个类或接口的总复杂性的内部限制。

我相信这意味着你不能在单个类中拥有超过65535个命名的“东西”,这也会限制枚举常量的数量。

  

如果看到一个有20亿个案例的交换机,我可能会杀死任何触及该代码的人。

幸运的是,这不可能发生:

  

每个非本机非抽象方法的代码量由LineNumberTable属性(第4.7.8节)中Code属性(第4.7.3节)的exception_table中索引的大小限制为65536字节。 ),以及LocalVariableTable属性(§4.7.9)。

答案 1 :(得分:9)

枚举元素的最大数量是2746.阅读规范非常具有误导性,导致我创建一个有缺陷的设计,假设我永远不会达到64K甚至32K的高水位。不幸的是,这个数字远低于规格似乎表明的数字。作为测试,我尝试了以下Java 7和Java 8:将以下代码重定向到一个文件,然后编译生成的.java文件。

    System.out.println("public enum EnumSizeTest {");
    int max = 2746;
    for ( int i=0; i<max; i++) {
        System.out.println("VAR"+i+",");
    }
    System.out.println("VAR"+max+"}");

结果,2746个有效,2747没有。

在2746个条目之后,编译器会抛出一个代码太大的错误,比如

  

EnumSizeTest.java:2:错误:代码太大

反编译此Enum类文件,限制似乎是由为静态构造函数(主要)中的每个枚举值生成的代码引起的。

答案 2 :(得分:7)

好吧,在jdk1.6上我达到了这个限制。有人在xsd中有10,000个枚举,当我们生成时,我们得到一个60,000行枚举文件,我得到一个很好的java编译器错误

[错误]无法执行目标org.apache.maven.plugins:maven-compiler-plugin:2.0.2:在项目框架上编译(default-compile):编译失败 [错误] /Users/dhiller/Space/ifp-core/framework/target/generated-sources/com/framework/util/LanguageCodeSimpleType.java:[7627,4]代码太大

所以很可能这个限制比这里的其他答案要低得多,或者生成的评论等也会占用太多空间。注意java编译器错误中的行号是7627,但是如果行限制是7627,我想知道行长度限制是什么;)这可能是类似的。即。限制可能不是基于枚举的数量,而是基于行长限制或文件限制中的行数,因此您可以将枚举重命名为A,B等,以使更多的枚举适合枚举。

我无法相信有人写了一个带有10,000枚枚举的xsd ......他们必须已经生成了xsd的这一部分。

答案 3 :(得分:7)

枚举肯定有限制,主要(硬)限制大约32K值。它们受Java类最大值的限制,这两个常量池和#39; (64K条目)和 - 在某些编译器版本中 - 对静态初始化程序的方法大小限制(64K字节码)。

&#39;枚举&#39;在内部初始化,每个值使用两个常量 - FieldRef和Utf8字符串。这给出了&#34;硬限制&#34;在~32K值。

较旧的编译器(至少Eclipse Indigo)也遇到了静态初始化方法大小的问题。使用24字节的字节码来实例化每个值&amp;将它添加到values数组中。可能会遇到约2730个值的限制。

较新的编译器(至少JDK 7)会自动将大型静态初始化程序拆分为名为" enum constant initialization$2"" enum constant initialization$3"等的方法,因此不受第二个限制的约束。

您可以通过javap -v -c YourEnum.class反汇编字节码,看看它是如何工作的。

[理论上可以写一个&#34;旧式&#34; Enum类作为手动编码的Java,打破32K的限制并接近接近64K的值。方法是通过 reflection 初始化枚举值,以避免在池中需要字符串常量。我测试了这种方法,它在Java 7中有效,但这种方法(安全问题)的可取性值得怀疑。]

编者注:Utf8是Java类文件IIRC中的内部类型,它不是要纠正的错字。

答案 4 :(得分:3)

Java中任何方法的最大大小为65536字节。虽然理论上你可以有一个大的开关或更多的枚举值,但它是你可能首先击中的方法的最大尺寸。

答案 5 :(得分:2)

Enum类使用int来跟踪每个值的序数,因此最大值最好与int相同,如果不低得多。

正如其他人所说,如果你不得不问你做错了

答案 6 :(得分:0)

Java 15+ 更新

在 JDK 15 中,枚举中常量的最大数量提高到大约 4103:https://bugs.openjdk.java.net/browse/JDK-8241798

这是通过将静态初始化器分成两部分来实现的:

Java 15 之前(伪代码):

enum E extends Enum<E> {
    ...

    static {
        C1 = new E(...);
        C2 = new E(...);
        ...
        CN = new E(...);
        $VALUES = new E[N];
        $VALUES[0] = C1;
        $VALUES[1] = C2;
        ...
        $VALUES[N-1] = CN;
    }
}

从 Java 15 开始:

enum E extends Enum<E> {
    ...

    static {
        C1 = new E(...);
        C2 = new E(...);
        ...
        CN = new E(...);
        $VALUES = $values();
    }

    private static E[] $values() {
        E[] array = new E[N];
        array[0] = C1;
        array[1] = C2;
        ...
        array[N-1] = CN;
        return array ;
    }
}

这允许静态初始化程序包含更多代码(直到达到 64 KB 限制),因此可以初始化更多枚举常量。

答案 7 :(得分:-1)

出于任何实际目的,没有最大数量本身。如果您需要在一个班级中定义数千个枚举,则需要重写您的程序。