2015-04-18 26 views
11

自Java 1.7以来,字符串可以与switch语句一起使用,这让我想到了一些东西。 switch将整数值的语句转换为跳转表,这比仅对if检查运行时计算的整数更快;可以用字符串进行类似的优化,还是仅仅是语法糖?切换字符串不仅仅是语法糖吗?

+0

'String'开关似乎使用固定大小的地图导致对于小数目的对数的性能来实现项目。请参阅http://java-performance.info/string-switch-performance/ – isnot2bad

回答

4

是的字符串切换是一种合成糖。 From here

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

2)它在内部使用equals方法进行比较,也就是说,如果你传递null,它会抛出java.lang.NullPointerException,所以要当心 那个。

3)switch语句中的字符串区分大小写,倾向于只使用 一种情况,并在将输入传递给 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中使用hashCode()equals()方法。

如所预期的,它使用的hashCode()方法用于切换和equals()方法用于验证 方法,这意味着它只是一个语法糖, 而不是一个内置的本地功能。

+1

最后两条语句让我感到矛盾:字节码效率的差异真的很大,如果它需要您创建新的较低/大写字母为了使用它? –

+4

所以......如果字节码更高效,那么它们不完全是语法糖。 – RealSkeptic

+0

@JeroenVannevel: - 这是矛盾的。我删除了该部分并添加了代码以使其更加清晰。 –

7

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

为什么这会更有效率?基本上随机密钥的开关不能使用跳转表。在最坏的情况下,跳转表需要2^32个条目。 – usr

+1

@usr即使跳转表无法使用,即使交换机在整数值上结束了一系列if-else检查,仍然通常比字符串值的一系列if-else检查更便宜。 – hvd

相关问题