用字符串切换的不仅仅是语法糖吗?

时间:2015-04-18 19:17:43

标签: java string switch-statement

从Java 1.7开始,字符串可以与switch语句一起使用,这让我有些疑惑。关于整数值的switch语句可以转换为跳转表,这比简单地对运行时计算的整数进行if检查要快;可以用字符串进行类似的优化,还是仅仅是语法糖?

2 个答案:

答案 0 :(得分:7)

编译器使用switch方法基于字符串值优化hashCode()语句,然后在字节码中使用查找表。这通常比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

答案 1 :(得分:6)

是的,带字符串的开关是一种合成糖。来自here

  

1)Switch中的字符串是语法糖,JVM级别没有变化。

     

2)在内部,它使用equals方法进行比较,这意味着,如果你   传递null它会抛出java.lang.NullPointerException,所以要小心   这一点。

     

3)switch语句中的字符串区分大小写,更喜欢只使用   一个案例并在将输入转换为首选案例之前将其转换为   切换声明。

同时检查 How String in Switch works in Java 7

如果您看到示例,请从同一链接:

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()方法。

  

正如预期的那样,它使用hashCode()方法进行切换和equals()   验证方法,这意味着它只是一种语法糖,   而不是内置的本机功能。