为什么这是交换(Java)发生的?
这个问题在这里已经有了答案:
可以切换语句拿对象还是不?
不,你不能在switch语句中使用任何任意对象。 这是在语言本身中指定的。 即使String
也只能从Java 7开始。 从JLS§14.11:
Expression的类型必须是char
, byte
, short
, int
, Character
, Byte
, Short
, Integer
, String
或enum
类型(第8.9节),否则会发生编译时错误。
带有字符串的switch语句使用hashCode比较进行编译,所以代码:
switch(s){
case "1":
case "2":
case "3":
}
编译后的样子如下所示:
switch(s.hashCode()){
case "1".hashCode():
case "2".hashCode():
case "3".hashCode():
}
实际上第7个JVM没有添加任何关于在交换机中使用字符串的具体内容。 只是一个小编辑技巧。 它可能通过hashCode()来比较字符串,因为这个函数被覆盖并且基于对象的内容。 这些信息在编译时出现。 尽管它对Strings这种方法的合法性对于任意对象来说绝对是不可接受的,因为hashCode()返回一个随机数。
这就是它在字节码中的外观:
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
使用字符串切换编译为使用整数切换。 如果偶然发现两个哈希码相等,则将字符串与equals()方法进行比较。 从JVM规范编译交换机。
在java中String
是非常特殊的。 String
被设计为处于primitive
和Class
。
可用于每个primitive
,Java允许(从7) String
也在切换(内部使用**equals**
方法)。
所以String
允许切换。 但不是每个Object.