带字符串的 switch 不仅仅是语法糖吗?
Is switch with strings more than just syntactic sugar?
从Java 1.7开始,字符串可以与switch语句一起使用,这让我想知道一些事情。 switch
将整数值的语句转换为跳转表,这比简单地对运行时计算的整数进行 if
检查要快;可以对字符串进行类似的优化吗?还是这只是语法糖?
是的,带字符串的开关是一种语法糖。来自 here
1) Strings in Switch are syntactic sugar, no change in JVM level.
2) Internally it uses equals method to compare, which means, if you
pass null it will throw java.lang.NullPointerException, so beware of
that.
3) Strings in switch statements are case sensitive, prefer to use only
one case and convert input to preferred case before passing them to
switch statement.
同时勾选 How String in Switch works in Java 7
来自同一个 link 如果您看到示例:
public class StringInSwitchCase{
public static void main(String[] args) {
String mode = args[0]; switch (mode) {
case "ACTIVE": System.out.println("Application is running on Active mode");
break;
case "PASSIVE": System.out.println("Application is running on Passive mode");
break;
case "SAFE": System.out.println("Application is running on Safe mode");
} } }
和反编译代码:
import java.io.PrintStream;
public class StringInSwitchCase{
public StringInSwitchCase() { }
public static void main(string args[]) {
String mode = args[0]; String s;
switch ((s = mode).hashCode()) {
default: break;
case -74056953: if (s.equals("PASSIVE")) {
System.out.println("Application is running on Passive mode"); }
break;
case 2537357: if (s.equals("SAFE")) { System.out.println("Application is running on Safe mode"); }
break;
case 1925346054: if (s.equals("ACTIVE")) { System.out.println("Application is running on Active mode"); }
break; } } }
你会发现Switch中的String是通过hashCode()
和equals()
的方式工作的。
As expected it uses hashCode() method for switching and equals()
method for verification, This means it's just a syntactic sugar,
rather than an inbuilt native functionality.
编译器使用 hashCode()
方法根据字符串值优化 switch
语句,然后在字节码中使用查找 table。这通常比 if
-else
语句更有效。
例如,以下内容:
String string = "x";
switch(string) {
case "x": System.out.println("x");
break;
case "y": System.out.println("y");
break;
case "z": System.out.println("z");
break;
}
转换成这个字节码:
ldc "x"
astore_1
aload_1
astore_2
iconst_m1
istore_3
aload_2
invokevirtual java/lang/String/hashCode()I
tableswitch 120
10
17
24
default: 30
aload_2
ldc "x"
invokevirtual java/lang/String/equals(Ljava/lang/Object;)Z
ifeq 30
iconst_0
istore_3
goto 30
aload_2
ldc "y"
invokevirtual java/lang/String/equals(Ljava/lang/Object;)Z
ifeq 30
iconst_1
istore_3
goto 30
aload_2
ldc "z"
invokevirtual java/lang/String/equals(Ljava/lang/Object;)Z
ifeq 30
iconst_2
istore_3
iload_3
tableswitch 0
32
36
40
default: 43
getstatic java/lang/System/out Ljava/io/PrintStream;
ldc "x"
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
goto 43
getstatic java/lang/System/out Ljava/io/PrintStream;
ldc "y"
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
goto 43
getstatic java/lang/System/out Ljava/io/PrintStream;
ldc "z"
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
return
从Java 1.7开始,字符串可以与switch语句一起使用,这让我想知道一些事情。 switch
将整数值的语句转换为跳转表,这比简单地对运行时计算的整数进行 if
检查要快;可以对字符串进行类似的优化吗?还是这只是语法糖?
是的,带字符串的开关是一种语法糖。来自 here
1) Strings in Switch are syntactic sugar, no change in JVM level.
2) Internally it uses equals method to compare, which means, if you pass null it will throw java.lang.NullPointerException, so beware of that.
3) Strings in switch statements are case sensitive, prefer to use only one case and convert input to preferred case before passing them to switch statement.
同时勾选 How String in Switch works in Java 7
来自同一个 link 如果您看到示例:
public class StringInSwitchCase{
public static void main(String[] args) {
String mode = args[0]; switch (mode) {
case "ACTIVE": System.out.println("Application is running on Active mode");
break;
case "PASSIVE": System.out.println("Application is running on Passive mode");
break;
case "SAFE": System.out.println("Application is running on Safe mode");
} } }
和反编译代码:
import java.io.PrintStream;
public class StringInSwitchCase{
public StringInSwitchCase() { }
public static void main(string args[]) {
String mode = args[0]; String s;
switch ((s = mode).hashCode()) {
default: break;
case -74056953: if (s.equals("PASSIVE")) {
System.out.println("Application is running on Passive mode"); }
break;
case 2537357: if (s.equals("SAFE")) { System.out.println("Application is running on Safe mode"); }
break;
case 1925346054: if (s.equals("ACTIVE")) { System.out.println("Application is running on Active mode"); }
break; } } }
你会发现Switch中的String是通过hashCode()
和equals()
的方式工作的。
As expected it uses hashCode() method for switching and equals() method for verification, This means it's just a syntactic sugar, rather than an inbuilt native functionality.
编译器使用 hashCode()
方法根据字符串值优化 switch
语句,然后在字节码中使用查找 table。这通常比 if
-else
语句更有效。
例如,以下内容:
String string = "x";
switch(string) {
case "x": System.out.println("x");
break;
case "y": System.out.println("y");
break;
case "z": System.out.println("z");
break;
}
转换成这个字节码:
ldc "x"
astore_1
aload_1
astore_2
iconst_m1
istore_3
aload_2
invokevirtual java/lang/String/hashCode()I
tableswitch 120
10
17
24
default: 30
aload_2
ldc "x"
invokevirtual java/lang/String/equals(Ljava/lang/Object;)Z
ifeq 30
iconst_0
istore_3
goto 30
aload_2
ldc "y"
invokevirtual java/lang/String/equals(Ljava/lang/Object;)Z
ifeq 30
iconst_1
istore_3
goto 30
aload_2
ldc "z"
invokevirtual java/lang/String/equals(Ljava/lang/Object;)Z
ifeq 30
iconst_2
istore_3
iload_3
tableswitch 0
32
36
40
default: 43
getstatic java/lang/System/out Ljava/io/PrintStream;
ldc "x"
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
goto 43
getstatic java/lang/System/out Ljava/io/PrintStream;
ldc "y"
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
goto 43
getstatic java/lang/System/out Ljava/io/PrintStream;
ldc "z"
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
return