Ste*_* B. 2 java compiler-construction compiler-errors
我知道这将无法编译:
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;
}
Run Code Online (Sandbox Code Playgroud)
我知道case语句是冲突的,并且编译器"不知道我正在谈论哪个'案例2'".我和我的一些同行在幕后想知道冲突是什么,并且听说过switch语句被转换成哈希映射.是这种情况,在编译期间,switch语句是否成为哈希映射,并且映射中的冲突会产生错误?
到目前为止,我已经浏览了Stack Overflow和Google的答案,而且信息必须已经存在,但我不确定如何正确地表达问题.提前致谢!
哈希映射只是一个方式,一个switch语句可能会被编译,但在任何情况下,你能想象有重复caseS作为想有多个值在规则相同的密钥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;
}
}
Run Code Online (Sandbox Code Playgroud)
你得到这个字节码:
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
Run Code Online (Sandbox Code Playgroud)
所以至少对于这个小switch,似乎使用跳转表.我听说开关的编译方式部分取决于它们的大小,但我不知道实现更改的确切位置.20个案例似乎仍被实施为跳转表......
结果表明Stringswitch语句的实现有点不同.从这个来源:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
你得到这个字节码:
public static void main(java.lang.String[]);
Code:
0: ldc #2 // String 2
2: astore_2
3: iconst_m1
4: istore_3
5: aload_2
6: invokevirtual #3 // Method java/lang/String.hashCode:()I
9: tableswitch { // 49 to 51
49: 36
50: 50
51: 64
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 #2 // 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 #6 // 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: 115
2: 126
default: 137
}
104: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
107: ldc #8 // String Happy
109: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
112: goto 145
115: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
118: ldc #10 // String Birthday
120: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
123: goto 145
126: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
129: ldc #11 // String To the ground!
131: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
134: goto 145
137: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
140: ldc #12 // String <3
142: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
145: return
Run Code Online (Sandbox Code Playgroud)
所以你仍然有跳桌,但你有两个.迂回处理后的比特 - 采取的哈希码,开关上,基于负载的情况下的另一常数,并从该做一个"正常"的开关(我想).但我想,同样的基本过程呢?
| 归档时间: |
|
| 查看次数: |
2303 次 |
| 最近记录: |