switch(jdk8)
本质
字节码
int类型
1 int = 4 byte
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | public static void switchTest( int a) { switch (a) { case 1 : System.out.println( "1" ); break ; case 2 : System.out.println( "2" ); break ; default : System.out.println( "3" ); break ; } } 字节码: 0 iload_0 1 lookupswitch 2 1 : 28 (+ 27 ) 2 : 39 (+ 38 ) default : 50 (+ 49 ) 28 getstatic # 3 <java/lang/System.out> ... |
switch的case <3 时,使用的lookupswitch指令实现;
lookupswitch
Access jump table by key match and jump 通过key匹配访问
The key must be of type int and is popped from the operand stack.
key 必须是int类型;
The key is compared against the match values.
If it is equal to one of them, then a target address is calculated by adding the corresponding offset to the address of the opcode of this lookupswitch instruction.
If the key does not match any of the match values, the target address is calculated by adding default to the address of the opcode of this lookupswitch instruction.
如果没有匹配的key,将会使用default;
Execution then continues at the target address.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | public static void switchTest( int a) { switch (a) { case 1 : System.out.println( "1" ); break ; case 2 : System.out.println( "2" ); break ; case 3 : System.out.println( "3" ); break ; default : System.out.println( "default" ); break ; } } 字节码: 0 iload_0 1 tableswitch 1 to 3 1 : 28 (+ 27 ) 2 : 39 (+ 38 ) 3 : 50 (+ 49 ) default : 61 (+ 60 ) 28 getstatic # 3 <java/lang/System.out> ... |
switch的case >=3 时,使用的tableswitch 指令实现;
tableswitch
Access jump table by index and jump 通过index访问
The index must be of type int and is popped from the operand stack. index必须是int类型;
If index is less than low or index is greater than high, then a target address is calculated by adding default to the address of the opcode of this tableswitch instruction.
Otherwise, the offset at position index - low of the jump table is extracted.
The target address is calculated by adding that offset to the address of the opcode of this tableswitch instruction.
Execution then continues at the target address.
byte类型
1byte = 8 bit
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | public static void switchTestByte( byte a) { switch (a) { case 1 : System.out.println( "1" ); break ; case 2 : System.out.println( "2" ); break ; default : System.out.println( "3" ); break ; } } 字节码: 0 iload_0 1 lookupswitch 2 1 : 28 (+ 27 ) 2 : 39 (+ 38 ) default : 50 (+ 49 ) 28 getstatic # 3 <java/lang/System.out> ... |
short类型
1 short = 2 byte
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | public static void switchTestShort( short a) { switch (a) { case 1 : System.out.println( "1" ); break ; case 2 : System.out.println( "2" ); break ; default : System.out.println( "3" ); break ; } } 字节码: 0 iload_0 1 lookupswitch 2 1 : 28 (+ 27 ) 2 : 39 (+ 38 ) default : 50 (+ 49 ) 28 getstatic # 3 <java/lang/System.out> ... |
char类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | public static void switchTestChar( char a) { switch (a) { case 1 : System.out.println( "1" ); break ; case 2 : System.out.println( "2" ); break ; default : System.out.println( "3" ); break ; } } 字节码: 0 iload_0 1 lookupswitch 2 1 : 28 (+ 27 ) 2 : 39 (+ 38 ) default : 50 (+ 49 ) 28 getstatic # 3 <java/lang/System.out> ... |
String类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | public static void switchTestString(String a) { switch (a) { case "a" : System.out.println( "a" ); break ; case "b" : System.out.println( "b" ); break ; default : System.out.println( "default" ); break ; } } 字节码: 0 aload_0 1 astore_1 2 iconst_m1 3 istore_2 4 aload_1 5 invokevirtual # 4 <java/lang/String.hashCode> //String 的hashCode值 8 lookupswitch 2 97 : 36 (+ 28 ) // "a"的Hashcode值 98 : 50 (+ 42 ) // "b"的Hashcode值 default : 61 (+ 53 ) 36 aload_1 37 ldc # 2 <a> 39 invokevirtual # 5 <java/lang/String.equals> 42 ifeq 61 (+ 19 ) 45 iconst_0 46 istore_2 47 goto 61 (+ 14 ) 50 aload_1 51 ldc # 6 <b> 53 invokevirtual # 5 <java/lang/String.equals> 56 ifeq 61 (+ 5 ) 59 iconst_1 60 istore_2 61 iload_2 ... |
String类型本质:用的hashcode值,也是int类型;
Enum类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | enum MyEnum { A,B,C } public static void switchTestEnum(MyEnum myEnum) { switch (myEnum) { case A: System.out.println( "a" ); break ; case B: System.out.println( "b" ); break ; default : System.out.println( "default" ); break ; } } 字节码: 0 getstatic # 4 <classtest/SwitchTest$ 1 .$SwitchMap$classtest$SwitchTest$MyEnum> 3 aload_0 4 invokevirtual # 5 <classtest/SwitchTest$MyEnum.ordinal> //枚举的ordinal方法 7 iaload 8 lookupswitch 2 1 : 36 (+ 28 ) 2 : 47 (+ 39 ) default : 58 (+ 50 ) 36 getstatic # 6 <java/lang/System.out> ... |
enum本质 :enum类型的ordinal方法(当前枚举值在枚举类型的序号0下标起始);
为什么switch会有类型限制?
字节码 lookupswitch、tableswitch指令 要求key/index 必须是int类型;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)