switch(jdk8)

发布时间 2023-11-17 15:57:11作者: anpeiyong

 

本质

字节码

int类型

  1 int = 4 byte

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.

 

 

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

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

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类型  

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类型

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类型

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类型