为什么Java中的switchcase语句这样工作?
|
参见英文答案 >
Why can’t I switch on a String?13个
解决方法通常,语言设计问题归结为“因为这是设计师决定做的事情”.这只是另一次.但是Java在C中有一些起源,这样做也是一样的,在80年代,这个决定被解释给我,因为那时编译器可以把开关转成一个跳转表:基本上每个代码块的地址都放在表和交换机成为范围检查,后跟表查找(通常使用您传入的值来索引到数组或至少链接数组列表)以获取地址,然后跳转到该地址.在这种情况下,只有整数才有意义.记住,电脑并不总是像现在那样快. C是在70年代初基于60年代末期的电脑设计的,电脑慢得多. 与Java和C相同的句法传统中的某些语言(如JavaScript)使得切换只是另一种写入方式,如果… else / if … else,并且不限制要检查的类型为整数类型,也许是因为在90年代被设计,成为一个现实的选择.或者也许只是因为JavaScript的设计者(Brendan Eich)喜欢这样. 下面,Baadshah问:
首先,让我们回头看一下int的情况: 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;
}
这样生成字节码: 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
我们可以看到在行动中的表查找. 那么你怎么用字符串呢?那么一个答案就是将开关转换成if … else if … else结构.但是他们做的比这更聪明:他们使用哈希码进行优化,然后使用equals来防止冲突: 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;
}
变为: 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
看看他们在那里做了什么现在基本上是两个开关:一个可以根据哈希码获得一个唯一的数字,但是用等号进行双重检查,然后是第二个发送. (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
