Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/348.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 带字符串的开关不仅仅是语法上的糖吗?_Java_String_Switch Statement - Fatal编程技术网

Java 带字符串的开关不仅仅是语法上的糖吗?

Java 带字符串的开关不仅仅是语法上的糖吗?,java,string,switch-statement,Java,String,Switch Statement,从Java1.7开始,字符串就可以与switch语句一起使用,这让我有些疑惑switch关于整数值的语句可以转换为跳转表,这比简单地对运行时计算的整数执行if检查要快;可以对字符串进行类似的优化吗?或者这只是语法上的糖分吗?Yes switch with string是一种语法上的糖分。从 1) 开关中的字符串是语法糖,JVM级别没有变化 2) 在内部,它使用equals方法进行比较,这意味着 传递null将抛出java.lang.NullPointerException,因此要小心 那个 3)

从Java1.7开始,字符串就可以与switch语句一起使用,这让我有些疑惑
switch
关于整数值的语句可以转换为跳转表,这比简单地对运行时计算的整数执行
if
检查要快;可以对字符串进行类似的优化吗?或者这只是语法上的糖分吗?

Yes switch with string是一种语法上的糖分。从

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

2) 在内部,它使用equals方法进行比较,这意味着 传递null将抛出java.lang.NullPointerException,因此要小心 那个

3) switch语句中的字符串区分大小写,建议仅使用 一个案例,并将输入转换为首选案例,然后再将其传递给 switch语句

同时检查

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

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; } } }
通过使用
hashCode()
equals()
方法,您将发现开关中的字符串起作用

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


编译器使用
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

String
开关似乎是使用一个固定大小的映射来实现的,这会导致少量项目的对数性能。看到这里的最后两条语句,我觉得很矛盾:如果需要创建一个新的大写/小写字符串来使用它,字节码效率的差异真的那么大吗?所以。。。如果字节码更有效,那么它们就不完全是语法糖。@Jeroenvanevel:-是的,这是矛盾的。我删除了这一部分,并添加了代码以使其更加清晰。也许在这里,我对语法糖的含义产生了疑问。自动装箱是一种语法糖(它只是推断一个方法调用)。Varargs是语法糖(它推断数组的创建)。这有点复杂。编译器计算哈希值并生成case语句。如果两个条件具有相同的哈希代码,则会得到If/else/else-If语句。这感觉比简单的语法糖要多一些。为什么这样会更有效率呢?打开基本上随机的键不能使用跳转表。在最坏的情况下,跳转表将需要2^32个条目。@usr即使跳转表不能使用,即使开关对整数值执行一系列if-else检查,这通常比对字符串值执行一系列if-else检查要便宜。