Why the switchcase statement in Java works like this?
为什么Java中的Twitter case语句只使用整数、短、字节和字符,而不是其他数据类型?有什么好处?请详细解释。
通常,语言设计问题归结为"因为设计师决定这样做。"这只是另一个时代。
但是Java有一些起源于C,它做了同样的事情,在80的时候,这个决定向我解释,因为编译器可以把开关转换成跳转表:基本上,每个代码块的地址都放在一个表中,EDCOX1×0个字变成一个范围检查,后面是一个表查找(通常索引成一个数组或一个数组)。t至少链接数组列表)使用传入的值获取地址,然后跳转到该地址。在那种情况下,只有整数才有意义。记住,计算机并不是一直像现在这样快。C是在70年代早期根据60年代后期的工作设计的,当时计算机速度慢得多。
与Java和C相同的一些语法传统,如JavaScript,使EDCOX1 0成为另一种编写EDCOX1×2的方法,并且不限制被检查的类型为整数类型,这可能是因为在90的设计中,这成为一个现实的选择。或者仅仅是因为JavaScript的设计者(BrendanEich)喜欢这样。
下面,Baadshah问:
Out of curiosity : Then now how its supporting Strings ??? can you please give some sort of idea ?
首先,让我们回顾一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | num = Integer.parseInt(args[0]); switch (num) { case 1: System.out.println("You used the special value one"); break; case 42: System.out.println("You used the special value forty-two"); break; case 67: System.out.println("You used the special value sixty-seven"); break; default: System.out.println("You used the a non-special value" + num); break; } |
产生这样的字节码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | 19: iload_2 20: lookupswitch { // 3 1: 56 42: 67 67: 78 default: 89 } 56: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream; 59: ldc #9 // String You used the special value one 61: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 64: goto 114 67: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream; 70: ldc #11 // String You used the special value forty-two 72: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 75: goto 114 78: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream; 81: ldc #12 // String You used the special value sixty-seven 83: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 86: goto 114 89: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream; 92: new #13 // class java/lang/StringBuilder 95: dup 96: invokespecial #14 // Method java/lang/StringBuilder."":()V 99: ldc #15 // String You used the a non-special value 101: invokevirtual #16 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 104: iload_2 105: invokevirtual #17 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 108: invokevirtual #18 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 111: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V |
我们可以看到
那么,如何用弦来实现呢?好吧,一个解决办法就是把
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | switch (str) { case"abc": System.out.println("You used the special value 'abc'"); break; case"def": System.out.println("You used the special value 'def'"); break; case"ghi": System.out.println("You used the special value 'ghi'"); break; default: System.out.println("You used the a non-special value '" + str +"'"); break; } |
变成:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | 124: aload 4 126: invokevirtual #19 // Method java/lang/String.hashCode:()I 129: lookupswitch { // 3 96354: 164 99333: 180 102312: 196 default: 209 } 164: aload 4 166: ldc #20 // String abc 168: invokevirtual #21 // Method java/lang/String.equals:(Ljava/lang/Object;)Z 171: ifeq 209 174: iconst_0 175: istore 5 177: goto 209 180: aload 4 182: ldc #22 // String def 184: invokevirtual #21 // Method java/lang/String.equals:(Ljava/lang/Object;)Z 187: ifeq 209 190: iconst_1 191: istore 5 193: goto 209 196: aload 4 198: ldc #23 // String ghi 200: invokevirtual #21 // Method java/lang/String.equals:(Ljava/lang/Object;)Z 203: ifeq 209 206: iconst_2 207: istore 5 209: iload 5 211: tableswitch { // 0 to 2 0: 236 1: 247 2: 258 default: 269 } 236: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream; 239: ldc #24 // String You used the special value 'abc' 241: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 244: goto 299 247: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream; 250: ldc #25 // String You used the special value 'def' 252: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 255: goto 299 258: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream; 261: ldc #26 // String You used the special value 'ghi' 263: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 266: goto 299 269: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream; 272: new #13 // class java/lang/StringBuilder 275: dup 276: invokespecial #14 // Method java/lang/StringBuilder."":()V 279: ldc #27 // String You used the a non-special value ' 281: invokevirtual #16 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 284: aload_3 285: invokevirtual #16 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 288: ldc #28 // String ' 290: invokevirtual #16 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 293: invokevirtual #18 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 296: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V |
看看他们在那里做了什么?现在基本上是两个
JDK6 switch语句处理char、byte、int基元数据类型和枚举。在JDK7中,他们认识到java.lang.string也是一个常量,并且已经被添加到switch语句支持的数据类型列表中。
例如,以下代码在JDK7中工作正常。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public static void OpenSource(String language) { switch (language) { case"PERL": System.out.println("PERL"); break; case"Python": System.out.println("Python"); break; case"Ruby": System.out.println("Ruby"); break; case"PHP": System.out.println("PHP"); break; default: throw new IllegalArgumentException(); } |
}