switch ステートメントは一連の if ステートメントとして表すことができますが、Java の switch ステートメントをバイトコードにコンパイルするときは、別のアプローチが使用されるようです。
- バイトコードで使用される表現は何ですか?
- この代替表現は効率上の理由によるものだと思いますが、効率は if ステートメントの表現と比べてどうでしょうか?
- この表現を使用することにつながった他の考慮事項はありますか?
switch ステートメントは一連の if ステートメントとして表すことができますが、Java の switch ステートメントをバイトコードにコンパイルするときは、別のアプローチが使用されるようです。
仕様を読んでください。Java では、switch ステートメントをコーディングすると、さまざまなことに応じて、switch がバイトコードの tableswitch 命令に変換されます。基本的にジャンプ台。JITがバイトコードをより効率的なものに最適化できる場合、バイトコードがどのように見えるかは無関係かもしれません。もちろん、これはプラットフォームに依存します。
この単純な JavaScript の例を考えてみましょう
var SwitchCases = [
// case 1
function() { return "one"; },
// case 2
function() { return "two"; },
// case 3
function() { return "three"; },
// default
function() { return ""; }
];
var SwitchCaseMin = 1;
var SwitchCaseMax = 3;
var SwitchCaseDefault = true;
function FakeSwitchCase(switch) {
if(switch > SwitchCaseMax || switch < SwitchCaseMin) {
if(SwitchCaseDefault == true) {
return SwitchCases[SwitchCases.length-1]();
}
} else {
return SwitchCases[switch - SwitchCaseMin]();
}
}
重要な部分は
SwitchCases[switch - SwitchCaseMin]();
多くのケースがあり、それらを評価するコードがそれ以上大きくならない場合を想像してみてください。ただし、IF..ELSE IF...ELSE を使用すると、ケースが追加されるたびに実行時間が長くなります。
実際のスイッチ ケースの実装では、SwitchCases (上記のコードから) は、Case コード ブロックが表示される関数内の場所へのラベル (読み取り: オフセット) の配列/ルックアップ テーブルになります。
編集
Java では、上記の switch ケースは次のバイト コードにコンパイルされます。
[tableswitch 0xAA]
[padding bytes 0x00 or 0x0000 or 0x000000]
[offset of SwitchCases[3]] // default case
[SwitchCaseMin] // 1
[SwitchCaseMax] // 3
[offset of SwitchCases[0]] // case 1
[offset of SwitchCases[1]] // case 2
[offset of SwitchCases[2]] // case 3