我知道这将无法编译:
int caseNum = 2;
switch(caseNum)
{
case 2:
System.out.println("Happy");
break;
case 2:
System.out.println("Birthday");
break;
case 2:
System.out.println("To the ground!");
break;
default:
System.out.println("<3");
break;
}
我知道案例陈述是冲突的,而且编制者并不知道案件2&#39;我在谈论&#34;。我和我的一些同行在幕后想知道冲突是什么,并且听说过switch语句被转换成哈希映射。是这种情况,在编译期间,switch语句是否成为哈希映射,并且映射中的冲突会产生错误?
到目前为止,我已经浏览了Stack Overflow和Google的答案,而且信息必须已经存在,但我不确定如何正确地表达问题。提前谢谢!
答案 0 :(得分:7)
哈希映射只是汇编语句可以编译的一种方式,但无论如何,你可以设想重复case
s,试图在常规{{1}中为同一个密钥设置多个值}}。编译器不知道哪个值对应于键,因此发出错误。
HashMap
语句也可以编译成跳转表,在这种情况下,由于非常相似的原因,这仍然是模糊的 - 对于相同的跳转位置,您有多种不同的可能性。
switch
语句也可以编译成二进制搜索,在这种情况下,您仍然会遇到相同的问题 - 搜索相同键的多个不同结果。
万一你好奇,我做了一个小测试用例,看看switch
将javac
编译成什么。从这个(稍加修改)来源:
switch
你得到这个字节码:
public static void main(final String[] args) {
final int caseNum = 2;
switch (caseNum) {
case 1:
System.out.println("Happy");
break;
case 2:
System.out.println("Birthday");
break;
case 3:
System.out.println("To the ground!");
break;
default:
System.out.println("<3");
break;
}
}
所以至少对于这个小public static void main(java.lang.String[]);
Code:
0: iconst_2
1: tableswitch { // 1 to 3
1: 28
2: 39
3: 50
default: 61
}
28: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
31: ldc #3 // String Happy
33: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
36: goto 69
39: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
42: ldc #5 // String Birthday
44: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
47: goto 69
50: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
53: ldc #6 // String To the ground!
55: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
58: goto 69
61: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
64: ldc #7 // String <3
66: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
69: return
,似乎使用了跳转表。我听说开关的编译方式部分取决于它们的大小,但我不知道实现更改的确切位置。 20个案例似乎仍被实施为跳转表......
结果switch
切换语句的实现略有不同。从这个来源:
String
你得到这个字节码:
public static void main(final String[] args) {
final String caseNum = "2";
switch (caseNum) {
case "1":
System.out.println("Happy");
break;
case "2":
System.out.println("Birthday");
break;
case "3":
System.out.println("To the ground!");
break;
default:
System.out.println("<3");
break;
}
}
所以你仍然有跳桌,但你有两个。一个环形交叉过程的一点 - 取哈希码,打开它,根据案例加载另一个常量,从那里做一个&#34;正常&#34;开关(我想)。但我想,同样的基本过程呢?
答案 1 :(得分:0)
历史上,switch
语句可以/可以实现为跳转表(即值到目标地址的映射)。根据表的实现,可能不可能有两个条目用于指向不同地址的相同值。即使有可能,您将如何处理该重复值?从第一个处理程序返回然后转到第二个处理程序?永远不要执行第二个处理程序?
允许这样做是没有意义的。