Why does the switchcase statement in Java work like this?
See the English answer > why can't I switch on a string? 13
Solution
Usually, the problem of language design comes down to "because this is what the designer decides to do" This is just another time
However, Java has some origins in C, and the same is true. In the 1980s, this decision was explained to me, because at that time, the compiler could turn the switch into a jump table: basically, the address of each code block was placed in the table and switch to become a range check, followed by table lookup (usually using the value you passed in to index the array or at least link the array list) to obtain the address, Then jump to the address In this case, only integers make sense Remember, computers are not always as fast as they are now C was designed in the early 1970s based on computers in the late 1960s. Computers are much slower
Some languages in the same syntactic tradition as Java and C (such as JavaScript) make switching just another writing method. If... Else / if... Else, and the type to be checked is not limited to integer type, it may be because it was designed and became a realistic choice in the 1990s Or maybe it's just because the JavaScript Designer (Brendan EICH) likes it
Next, baadshah asked:
First, let's look back at 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; }
The bytecode is generated as follows:
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
We can see the table lookup in action
So how do you use strings? Then one answer is to convert the switch into an if... Else if... Else structure But they are smarter than this: they use hash codes for optimization, and then use equals to prevent conflicts:
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; }
Change to:
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
Look what they did there. Now there are basically two switches: one can get a unique number according to the hash code, but double check with the equal sign, and then send the second