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

Pau*_*nta 12 java string switch-statement

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

man*_*uti 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;
}
Run Code Online (Sandbox Code Playgroud)

转换为此字节码:

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
Run Code Online (Sandbox Code Playgroud)


Rah*_*thi 6

是的,带字符串的开关是一种合成糖.从这里开始

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

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

3)switch语句中的字符串区分大小写,更喜欢只使用一种情况,并在将输入传递给switch语句之前将输入转换为首选大小写.

另请参阅检查Switch中的字符串如何在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"); 
        } } }
Run Code Online (Sandbox Code Playgroud)

和反编译代码:

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; } } }
Run Code Online (Sandbox Code Playgroud)

你会发现Switch中的String工作原理是使用hashCode()equals()方法.

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

  • 所以...如果字节码更有效,那么它们就不是语法糖. (4认同)