Java 7 では、ステートメントの式にstring
オブジェクトを含めることができます。誰かが公式文書switch
から以下の声明を説明できますか?
一般に、Java コンパイラは、連結された if-then-else ステートメントからよりも、String オブジェクトを使用する switch ステートメントからより効率的なバイトコードを生成します。
Java 7 では、ステートメントの式にstring
オブジェクトを含めることができます。誰かが公式文書switch
から以下の声明を説明できますか?
一般に、Java コンパイラは、連結された if-then-else ステートメントからよりも、String オブジェクトを使用する switch ステートメントからより効率的なバイトコードを生成します。
クラスの2つのバージョンがある、例えば
とif-then-else
:
public class IfThenElseClass {
public static void main(String[] args) {
String str = "C";
if ("A".equals(str)) {
} else if ("B".equals(str)) {
} else if ("C".equals(str)) {
}
}
}
とswitch
:
public class SwitchClass {
public static void main(String[] args) {
String str = "C";
switch (str) {
case "A":
break;
case "B":
break;
case "C":
break;
}
}
}
バイトコードを見てみましょう。if-then-else
バージョンのバイトコードの取得:
Compiled from "CompileSwitch.java"
public class CompileSwitch {
public CompileSwitch();
Code:
0: aload_0
1: invokespecial #8 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #16 // String C
2: astore_1
3: ldc #18 // String A
5: aload_1
6: invokevirtual #20 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
9: ifne 28
12: ldc #26 // String B
14: aload_1
15: invokevirtual #20 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
18: ifne 28
21: ldc #16 // String C
23: aload_1
24: invokevirtual #20 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
27: pop
28: return
}
switch
バージョンのバイトコードの取得:
Compiled from "CompileSwitch.java"
public class CompileSwitch {
public CompileSwitch();
Code:
0: aload_0
1: invokespecial #8 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #16 // String C
2: astore_1
3: aload_1
4: dup
5: astore_2
6: invokevirtual #18 // Method java/lang/String.hashCode:()I
9: lookupswitch { // 3
65: 44
66: 56
67: 68
default: 77
}
44: aload_2
45: ldc #24 // String A
47: invokevirtual #26 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
50: ifne 77
53: goto 77
56: aload_2
57: ldc #30 // String B
59: invokevirtual #26 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
62: ifne 77
65: goto 77
68: aload_2
69: ldc #16 // String C
71: invokevirtual #26 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
74: ifne 77
77: return
}
equals
最初のバージョンでは、条件が見つかるまで、各条件のメソッドを呼び出して文字列を比較します。
2番目のバージョンではhashCode
、文字列の最初に取得されます。次に、これは値<code>hashCodeeachと比較されますcase
。を参照してくださいlookupswitch
。これらの値のいずれかが繰り返される場合は、たまたまのコードを実行しますcase
。equals
それ以外の場合は、関連付けられているケースのメソッドを呼び出します。これは、equals
メソッドのみを呼び出すよりもはるかに高速です。
switch
文字列のハッシュセットでのルックアップが文字列のリストでのルックアップよりも高速であるのと同じ理由で、文字列でのルックアップは高速になる可能性があります。O(1)
ではなくでルックアップを実行できます。O(N)
ここN
で、は文字列の数です。
switch
これは計算されたジャンプであるため、ステートメントのチェーンよりも効率的であることを思い出してくださいif-then-else
。コード内のオフセットは値に基づいて計算され、そのオフセットへのジャンプが実行されます。Javaは、ハッシュマップやハッシュセットで採用されているメカニズムと同様のメカニズムを使用して、文字列に対して同様のトリックを引き出すことができます。
次のような方が効率的です。
switch(yourString) {
case "text1":
// your code
break;
case "text2":
// etc.
}
特派員より:
if (yourString.equals("text1")) {
// your code
} else if (yourString.equals("text2")) {
// etc.
}
それが何を意味するのか、または私が理解しているのは、文字列を使用してswitchステートメントから作成されたバイトコード(Javaクラスをコンパイルするとき)は、文字列を使用してif-elseステートメントから作成されたバイトコードよりも高速で効率的であるということです。どちらも同じ仕事をすることができます.ビットスイッチは明らかにより効率的です.
switch (str) {
case "A":
// do something
break;
case "B":
// do something
break;
default:
//do something
break;
}
よりも良い
if(str.equals("A")) {
//do something
} else if(str-equals("B")) {
//do something
} else {
//do something
}