web-dev-qa-db-ja.com

Javaの列挙型要素の最大数

Javaの列挙型で許可される要素の最大数はいくつですか?

Switchステートメントの最大ケース数を知りたいと思いました。 switchで許可される最大のプリミティブ型はintであるため、-2,147,483,648から2,147,483,647までのケースと1つのデフォルトケースがあります。ただし、列挙型も許可されています...だから質問..

28
Rnet

クラスファイル形式仕様 から:

クラスごとまたはインターフェイスごとの定数プールは、ClassFile構造(§4.1)の16ビットconstant_pool_countフィールドによって65535エントリに制限されています。これは、単一のクラスまたはインターフェイスの全体的な複雑さに対する内部制限として機能します。

これは、単一のクラスに65535を超える名前の「things」を含めることができないことを意味すると思います。これにより、列挙型定数の数も制限されます。

20億ケースのスイッチが表示された場合、そのコードに触れた人はおそらく殺します。

幸いなことに、それは起こり得ません。

非ネイティブ、非抽象メソッドごとのコードの量は、Code属性(§4.7.3)のexception_table、LineNumberTable属性(§4.7.8)、およびのインデックスのサイズによって65536バイトに制限されます。 LocalVariableTable属性(§4.7.9)。

32
Thilo

列挙型要素の最大数は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クラスファイルを逆コンパイルすると、制限は静的コンストラクターの各enum値に対して生成されたコードによって引き起こされているように見えます(ほとんどの場合)。

12
Derek

列挙型には間違いなく制限があり、プライマリ(ハード)制限は約32K値です。それらはJavaクラスの最大値、「定数プール」(64Kエントリ)の両方、および一部のコンパイラバージョンでは静的初期化子のメソッドサイズ制限(64Kバイトコード)の対象となります。

「列挙型」の初期化は内部的に行われ、値ごとに2つの定数(FieldRefとUtf8文字列)を使用します。これにより、最大32Kの値で「ハード制限」が発生します。

古いコンパイラー(少なくともEclipse Indigo)でも、静的初期化子のメソッドサイズに関して問題が発生します。各値をインスタンス化してvalues配列に追加するには、24バイトのバイトコードが必要です。約2730の値の制限に遭遇する可能性があります。

新しいコンパイラ(少なくともJDK 7)は、大きな静的初期化子を" enum constant initialization$2"" enum constant initialization$3"などの名前のメソッドに自動的に分割するため、2番目の制限は適用されません。

javap -v -c YourEnum.classを介してバイトコードを分解し、これがどのように機能するかを確認できます。

[理論的には、「古いスタイル」のEnumクラスをハンドコード化されたJavaとして記述し、32Kの制限を超えて、64Kの値に近づけることが可能かもしれません。アプローチは、プールに文字列定数が必要ないように、列挙値を反射で初期化することです。私はこのアプローチをテストし、Java 7で動作しますが、そのようなアプローチの望ましさ(安全性の問題)には疑問があります。]

編集者への注意:Utf8はJavaクラスファイルIIRCの内部型であり、修正されるタイプミスではありません。

7
Thomas W

さて、jdk1.6で私はこの制限に達しました。誰かがxsdに10,000の列挙型を持っていて、生成すると60,000行の列挙型ファイルを取得し、次のニースJavaコンパイラエラーを取得します。

[エラー]プロジェクトフレームワークでゴールorg.Apache.maven.plugins:maven-compiler-plugin:2.0.2:compile(default-compile)を実行できませんでした:コンパイルに失敗しました[エラー]/Users/dhiller/Space/ifp-core /framework/target/generated-sources/com/framework/util/LanguageCodeSimpleType.Java:[7627,4]コードが大きすぎます

おそらく、制限はここにある他の回答よりもはるかに低いですORおそらく生成されたコメントなどがあまりにも多くのスペースを占めています。 Javaコンパイラエラーの行番号が7627であることに注意してください。ただし、行制限が7627の場合、行長制限は何であるか疑問に思います;)これは類似している可能性があります。すなわち。制限は列挙型の数ではなく、行の長さの制限またはファイル制限内の行数に基づいている場合があるため、列挙型の名前をA、Bなどに変更して、より多くの列挙型を列挙型に収めるようにします。

誰かが10,000列挙型のxsdを書いたとは信じられません。彼らはxsdのこの部分を生成したに違いありません。

7
Dean Hiller

Javaのメソッドの最大サイズは65536バイトです。理論的には大きなスイッチまたはより多くの列挙値を持つことができますが、最初にヒットする可能性のあるメソッドの最大サイズです。

3
Peter Lawrey

Enumクラスはintを使用して各値の序数を追跡するため、maxは、それほど低くはないにしても、せいぜいintと同じになります。

そして他の人が言ったように、あなたがそれを間違っていると尋ねなければならないなら

2
Brad Mace