この機能は、今後の Java バージョンに組み込まれる予定ですか?
switch
Java のステートメントが技術的に機能する理由など、なぜこれができないのかを誰か説明してもらえますか?
ベストアンサー1
ケース付きスイッチ文がString
実装されましたJava SE 716歳以上最初にリクエストされた後。遅延の明確な理由は明らかにされていないが、パフォーマンスに関係している可能性が高い。
JDK 7での実装
この機能は現在、javac
「脱糖」プロセスを経て;String
宣言で定数を使用するクリーンな高レベルの構文は、case
コンパイル時にパターンに従ってより複雑なコードに拡張されます。結果として得られるコードは、常に存在する JVM 命令を使用します。
switch
コンパイル時に、case付きのはString
2 つのスイッチに変換されます。最初のスイッチは、各文字列を一意の整数 (元のスイッチ内の位置) にマップします。これは、最初にラベルのハッシュ コードをオンにすることで行われます。対応する case は、if
文字列の等価性をテストするステートメントです。ハッシュに衝突がある場合、テストはカスケード になりますif-else-if
。2 番目のスイッチは、元のソース コードのそれをミラーリングしますが、case ラベルを対応する位置に置き換えます。この 2 段階のプロセスにより、元のスイッチのフロー制御を簡単に保持できます。
JVM のスイッチ
のより技術的な詳細についてはswitch
、JVM仕様を参照してください。switch文のコンパイルについて説明します。簡単に言うと、ケースで使用される定数のスパース性に応じて、スイッチに使用できる 2 つの異なる JVM 命令があります。どちらも、効率的に実行するために、各ケースに整数定数を使用することに依存しています。
定数が密な場合、それらは(最小値を減算した後)命令ポインターのテーブル(命令)へのインデックスとして使用されますtableswitch
。
定数がまばらな場合は、正しいケース(lookupswitch
命令)のバイナリ検索が実行されます。
switch
オブジェクトで をデシュガーリングする場合String
、両方の命令が使用される可能性があります。 は、lookupswitch
ケースの元の位置を見つけるためのハッシュ コードの最初のスイッチに適しています。 結果として得られる序数は に自然に適合しますtableswitch
。
どちらの命令も、各ケースに割り当てられた整数定数をコンパイル時にソートする必要があります。実行時には、O(1)
のパフォーマンスはのパフォーマンスtableswitch
よりも一般的に優れているように見えますが、テーブルが空間と時間のトレードオフを正当化するのに十分な密度であるかどうかを判断するには、ある程度の分析が必要です。Bill Venners は次のように書いていますO(log(n))
。lookupswitch
素晴らしい記事では、この点についてさらに詳しく説明するとともに、他の Java フロー制御命令の内部についても説明します。
JDK 7以前
JDK 7より前では、ベースのスイッチenum
を近似できましたString
。これは、静的valueOf
コンパイラによってすべてのenum
型に対して生成されるメソッド。例:
Pill p = Pill.valueOf(str);
switch(p) {
case RED: pop(); break;
case BLUE: push(); break;
}