Why is this happenning with switch (Java)?
它非常清楚,开关语句可以在Java中使用字符串值,类似于此:
1 2 3 4 |
将始终编译..s是字符串类型的对象….但是另一方面,switch语句不能接受其他类的对象?为什么会发生这种情况,我如何用合适的答案来验证这个问题。
switch语句是否可以接受对象?
Can switch statement take objects or not?
不,不能在switch语句中使用任意对象。这是在语言本身中指定的。即使是EDCOX1的0度,也只允许从Java 7起。摘自JLS§;14.11:
The type of the Expression must be
char ,byte ,short ,int ,Character ,Byte ,Short ,Integer ,String , or anenum type (§8.9), or a compile-time error occurs.
带有字符串的switch语句是通过哈希代码比较编译的,因此代码:
1 2 3 4 5 | switch(s){ case"1": case"2": case"3": } |
编译后如下:
1 2 3 4 5 | switch(s.hashCode()){ case"1".hashCode(): case"2".hashCode(): case"3".hashCode(): } |
实际上,第7个JVM没有添加任何关于在交换机中使用字符串的具体内容。只是一个小小的编译技巧。它可以通过hashcode()比较字符串,因为此函数被重写并基于对象的内容。此信息在编译时存在。虽然这种方法对于字符串是合法的,但对于任意对象是绝对不可接受的,因为hashcode()返回一个随机数。
这就是它在字节码中的样子:
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 | 11: tableswitch { // 49 to 51 49: 36 //"1".hashCode() 50: 50 //"2".hashCode() 51: 64 //"3".hashCode() default: 75 } 36: aload_2 37: ldc #4 // String 1 39: invokevirtual #5 // Method java/lang/String.equals:(Ljava/lang/Object;)Z 42: ifeq 75 45: iconst_0 46: istore_3 47: goto 75 50: aload_2 51: ldc #6 // String 2 53: invokevirtual #5 // Method java/lang/String.equals:(Ljava/lang/Object;)Z 56: ifeq 75 59: iconst_1 60: istore_3 61: goto 75 64: aload_2 65: ldc #7 // String 3 67: invokevirtual #5 // Method java/lang/String.equals:(Ljava/lang/Object;)Z 70: ifeq 75 73: iconst_2 74: istore_3 75: iload_3 76: tableswitch { // 0 to 2 0: 104 1: 104 2: 104 default: 104 } 104: return |
switch with strings被编译为switch with ints。如果意外地两个哈希代码相等,则将字符串与equals()方法进行比较。根据JVM规范编译交换机。
在Java中,EDCOX1 0是非常特殊的。
使每个EDCOX1都适用于3,Java允许(从7)EDCOX1,0,也在交换机(内部使用EDCOX1,7,7方法)。
所以