Java中switch的實(shí)現(xiàn)原理

目前Java中switch語(yǔ)句支持的數(shù)據(jù)類(lèi)型包括:byte、short、int、char、String以及Enum,那么switch語(yǔ)句是如何實(shí)現(xiàn)的呢?

一、switch對(duì)整型的支持

public void switchInt(int value) {
    switch (value) {
        case 1:
            System.out.println("1");
            break;
        case 2:
            System.out.println("2");
            break;
        default:
            System.out.println("Error value");
            break;
    }
}

使用javap -c進(jìn)行反編譯可以看到:

  public void switchInt(int);
    Code:
       0: iload_1
       1: lookupswitch  { // 2
                     1: 28
                     2: 39
               default: 50
          }
      28: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
      31: ldc           #14                 // String 1
      33: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      36: goto          58
      39: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
      42: ldc           #15                 // String 2
      44: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      47: goto          58
      50: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
      53: ldc           #16                 // String Error value
      55: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      58: return

可以看到,switch對(duì)整型的支持是直接比較int的值(如果換做byte和short,反編譯后是一樣的)。

二、switch對(duì)char的支持

public void switchChar(char value) {
    switch (value) {
        case 'a':
            System.out.println("a");
            break;
        case 'b':
            System.out.println("b");
            break;
        default:
            System.out.println("Error value");
            break;
    }
}

使用javap -c進(jìn)行反編譯可以看到:

  public void switchChar(char);
    Code:
       0: iload_1
       1: lookupswitch  { // 2
                    97: 28
                    98: 39
               default: 50
          }
      28: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
      31: ldc           #17                 // String a
      33: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      36: goto          58
      39: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
      42: ldc           #18                 // String b
      44: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      47: goto          58
      50: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
      53: ldc           #16                 // String Error value
      55: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      58: return

可以看到,switch對(duì)char的支持是將char轉(zhuǎn)換成int值,再做比較的。

三、switch對(duì)字符串的支持

public void switchString(String str) {
    switch (str) {
        case "hello":
            System.out.println("hello");
            break;
        case "welcome":
            System.out.println("welcome");
            break;
        default:
            System.out.println("Error value");
            break;
    }
}

使用javap -c進(jìn)行反編譯可以看到:

  public void switchString(java.lang.String);
    Code:
       0: aload_1
       1: astore_2
       2: iconst_m1
       3: istore_3
       4: aload_2
       5: invokevirtual #19                 // Method java/lang/String.hashCode:()I
       8: lookupswitch  { // 2
              99162322: 36
            1233099618: 50
               default: 61
          }
      36: aload_2
      37: ldc           #20                 // String hello
      39: invokevirtual #21                 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
      42: ifeq          61
      45: iconst_0
      46: istore_3
      47: goto          61
      50: aload_2
      51: ldc           #22                 // String welcome
      53: invokevirtual #21                 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
      56: ifeq          61
      59: iconst_1
      60: istore_3
      61: iload_3
      62: lookupswitch  { // 2
                     0: 88
                     1: 99
               default: 110
          }
      88: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
      91: ldc           #20                 // String hello
      93: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      96: goto          118
      99: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
     102: ldc           #22                 // String welcome
     104: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
     107: goto          118
     110: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
     113: ldc           #16                 // String Error value
     115: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
     118: return

可以看到,switch對(duì)字符串的支持是先比較hashCode,再用equals做校驗(yàn),最后用得到的值再switch一次。

四、switch對(duì)枚舉類(lèi)型的支持

public void switchEnum(State state) {
    switch (state) {
        case Start:
            System.out.println("Start");
            break;
        case InProcessing:
            System.out.println("InProcessing");
            break;
        case Finished:
            System.out.println("Finished");
            break;
        default:
            System.out.println("Error state");
            break;
    }
}

使用javap -c進(jìn)行反編譯可以看到:

  public void switchEnum(pers.wukong.onestep.State);
    Code:
       0: getstatic     #6                  // Field pers/wukong/onestep/Test$1.$SwitchMap$pers$wukong$onestep$State:[I
       3: aload_1
       4: invokevirtual #7                  // Method pers/wukong/onestep/State.ordinal:()I
       7: iaload
       8: tableswitch   { // 1 to 3
                     1: 36
                     2: 47
                     3: 58
               default: 69
          }
      36: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
      39: ldc           #9                  // String Start
      41: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      44: goto          77
      47: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
      50: ldc           #11                 // String InProcessing
      52: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      55: goto          77
      58: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
      61: ldc           #12                 // String Finished
      63: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      66: goto          77
      69: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
      72: ldc           #13                 // String Error state
      74: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      77: return

switch對(duì)枚舉類(lèi)型的支持和我預(yù)想的不一樣,它是維護(hù)了一個(gè)SwitchMap,枚舉的ordinal()方法的返回值作為Key,value是從1開(kāi)始遞增的。switch比較的就是這個(gè)value值。

總結(jié)

switch其實(shí)都是通過(guò)int來(lái)實(shí)現(xiàn)的,不同的是,各種數(shù)據(jù)類(lèi)型轉(zhuǎn)換int的方式是不一樣的。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容