1. ホーム
  2. java

[解決済み] Stringでswitch文が使えないのはなぜですか?

2022-03-19 08:45:01

質問

この機能は、後のJavaバージョンに搭載されるのでしょうか?

なぜこれができないのか、誰か技術的な方法で説明してくれませんか、Javaの switch 文は機能するのでしょうか?

どのように解決するのですか?

でのSwitchステートメント String のケースが実装されました。 Java SE 7 は、少なくとも16年 は、最初にリクエストされてから 明確な理由は明らかにされていないが、おそらく性能に関係するものだろう。

JDK 7での実装

この機能は、現在 javac を、quot;de-sugar"処理で追加しました。 を使用したクリーンでハイレベルなシンタックスです。 String の定数 case の宣言は、コンパイル時にパターンに従ってより複雑なコードに展開されます。その結果、常に存在するJVM命令が使われる。

A switchString のケースは、コンパイル時に2つのスイッチに変換される。最初のスイッチは、各文字列を一意の整数(元のスイッチの位置)に対応付ける。これは、まずラベルのハッシュコードをスイッチすることで行われる。対応するケースは if 文は、文字列の等質性をテストします。ハッシュ上で衝突があった場合、テストはカスケード接続された if-else-if . 2番目のスイッチは、元のソースコードと同じですが、大文字と小文字のラベルを対応する位置に置き換えています。この2段階の処理により、元のスイッチのフロー制御を維持することが容易になります。

JVMのスイッチ

に関する技術的な深堀りは switch は、JVM仕様書を参照することができます。 switch文のコンパイル が記述されています。一言で言えば、スイッチに使えるJVM命令は、ケースによって使われる定数の疎密によって、2種類あります。どちらも、効率的に実行するために、各ケースで整数定数を使用することに依存します。

定数が密な場合、その定数は(最小値を引いた後の)インデックスとして、命令ポインタのテーブルである tableswitch 命令です。

定数がまばらな場合、正しいケースを探すためにバイナリサーチが実行されます。 lookupswitch という命令があります。

をデスガする際に switch オン String オブジェクトの場合、両方の命令が使用される可能性があります。そのため lookupswitch は、ハッシュコードの最初のスイッチで、ケースの元の位置を求めるのに適している。その結果得られる序列は、自然に tableswitch .

どちらの命令も、コンパイル時に各ケースに割り当てられた整数定数をソートしておく必要があります。実行時には O(1) の性能は tableswitch よりも一般的に良く見える。 O(log(n)) の性能は lookupswitch しかし、テーブルが十分な密度を持ち、時空間のトレードオフを正当化できるかどうかを判断するためには、いくつかの分析が必要です。Bill Vennersは次のように書いています。 素晴らしい記事 では、他のJavaフロー制御命令の裏側とともに、この点をより詳しく取り上げています。

JDK 7以前

JDK 7 より前のバージョン。 enum を近似することができます。 String -をベースにしたスイッチです。これは 静的な valueOf メソッドは、コンパイラがすべての enum 型になります。例えば

Pill p = Pill.valueOf(str);
switch(p) {
  case RED:  pop();  break;
  case BLUE: push(); break;
}