Java の switch ステートメントは内部でどのように機能しますか? 使用されている変数の値を、ケース パーツで指定された値とどのように比較しますか? または を使用しています==
か.equals()
、それともまったく別のものですか?
私は主に 1.7 より前のバージョンに興味があります。
Java の switch ステートメントは内部でどのように機能しますか? 使用されている変数の値を、ケース パーツで指定された値とどのように比較しますか? または を使用しています==
か.equals()
、それともまったく別のものですか?
私は主に 1.7 より前のバージョンに興味があります。
ない。lookupswitch
これは、基本的にテーブル ルックアップである JVM 命令を使用します。次の例のバイトコードを見てください。
public static void main(String... args) {
switch (1) {
case 1:
break;
case 2:
break;
}
}
public static void main(java.lang.String[]);
Code:
Stack=1, Locals=1, Args_size=1
0: iconst_1
1: lookupswitch{ //2
1: 28;
2: 31;
default: 31 }
28: goto 31
31: return
この回答からわかるように、Java switch
(少なくとも 1.7 より前) は常に==
または .equals()
にコンパイルされるとは限りません。代わりに、テーブル ルックアップを使用します。これは非常に小さなマイクロ最適化ですが、非常に多くの比較を行う場合、テーブル ルックアップはほとんど常に高速になります。
これはswitch
、密なキーをチェックするステートメントにのみ使用されることに注意してください。たとえば、すべての可能性について enum 値をチェックすると、おそらくこの主要な実装が生成されます (内部的に と呼ばれtableswitch
ます)。
よりまばらに入力されたキーのセットに対してチェックする場合、JVM はlookupswitch
. 代わりに、さまざまなキーと値を単純に比較し、本質的==
にそれぞれの可能性に対して最適化された比較を行います。これら 2 つの方法を説明するために、次の 2 つの switch ステートメントを考えてみましょう。
switch (value1) {
case 0:
a();
break;
case 1:
b();
break;
case 2:
c();
break;
case 3:
d();
break;
}
switch (value2) {
case 0:
a();
break;
case 35:
b();
break;
case 103:
c();
break;
case 1001:
d();
break;
}
最初の例ではテーブル ルックアップを使用する可能性が高く、もう 1 つの例では (基本的に)==
比較を使用します。
ここからコピペ
バイトコードには、テーブルスイッチとルックアップスイッチの 2 つの形式のスイッチがあります。1 つは密集したキー セットを想定し、もう 1 つは疎なキー セットを想定しています。JVM 仕様のコンパイル スイッチの説明を参照してください。列挙型の場合、序数が検出され、コードは int ケースとして続行されます。JDK7 で提案されている String の小さな機能の切り替えがどのように実装されるかは完全にはわかりません。
ただし、頻繁に使用されるコードは通常、適切な JVM でコンパイルされます。オプティマイザーは完全に愚かではありません。心配する必要はありません。最適化のための通常のヒューリスティックに従ってください。
ここで詳細な回答を見つけることができます
1.が登場する前はJava 7
でした。なぜなら、大文字と小文字を切り替えるために整数と文字を"=="
使用でき、それらがプリミティブであるため、 でなければならなかったからです。"=="
2.からJava 7
、文字列も switch case で許可されobject
、である文字列".equals"
が使用されます。
これを追加したいと思います...オブジェクト自体ではなく、を比較するために"=="
使用されます。を使用して、オブジェクトを比較します。Object Reference
Variable
".equals"
スイッチは、byte、short、char、および int プリミティブ データ型で機能します。また、列挙型 (列挙型で説明)、String クラス、および特定のプリミティブ型 (Character、Byte、Short、および Integer) をラップするいくつかの特別なクラスでも機能します。(ジャバ1.6)
プリミティブは と比較されます==
が、switch
メソッドは Java 1.6 (およびそれ以前) でこの種の比較を確実に使用します。
1.7より前のJavaを使用している場合、使用すると仮定します
==
intの場合、たとえばequalsを実行できず、enumの場合、equalsと==は同じを返すためです
編集
私の仮定は間違っており、ルックアップテーブルを使用しています。バイトコードでは次のようになります。
tableswitch
整数などのプリミティブ型を使用==
している場合、Java はそれらを比較するために使用します。文字列を使用している場合、Java はequals()
メソッドを使用して文字列が等しいかどうかをテストします。列挙型で switch ステートメントを使用している場合、==
とequals()
はどちらも同じであるため、どちらが使用されているかは問題ではありません。