dk7 switch 對 String 的支援

Brewin發表於2020-09-15

在jdk7之前,switch只能支援 byte、short、char、int或者其對應的封裝類以及Enum型別,在jdk7後,支援String型別。

在switch語句中,表示式的值不能是null,否則會在執行時丟擲NullPointerException。在case子句中也不能使用null,否則會出現編譯錯誤。

同時,case字句的值是不能重複的。對於字串型別的也一樣,但是字串中可以包含Unicode跳脫字元。重複值的檢查是在Java編譯器對Java原始碼進行相關的詞法轉換之後才進行的。也就是說,有些case字句的值雖然在原始碼中看起來是不同的,但是經詞法轉換之後是一樣的,就會在成編譯錯誤。比如:“男”和“\u7537”就是一個意思。

接下來我們就看一下,switch到底是如何實現的。

一、switch對整型支援的實現

下面是一段很簡單的Java程式碼,定義一個int型變數a,然後使用switch語句進行判斷。執行這段程式碼輸出內容為5,那麼我們將下面這段程式碼反編譯,看看他到底是怎麼實現的。

public class switchDemoInt {
    public static void main(String[] args) {
        int a = 5;
        switch (a) {
        case 1:
            System.out.println(1);
            break;
        case 5:
            System.out.println(5);
            break;
        default:
            break;
        }
    }
}
//output 5

反編譯後的程式碼如下:

public class switchDemoInt
{
    public switchDemoInt()
    {
    }
    public static void main(String args[])
    {
        int a = 5;
        switch(a)
        {
        case 1: // '\001'
            System.out.println(1);
            break;

        case 5: // '\005'
            System.out.println(5);
            break;
        }
    }
}

我們發現,反編譯後的程式碼和之前的程式碼比較除了多了兩行註釋以外沒有任何區別,那麼我們就知道,switch對int的判斷是直接比較整數的值

二、switch對字元型支援的實現

直接上程式碼:

public class switchDemoInt {
    public static void main(String[] args) {
        char a = 'b';
        switch (a) {
        case 'a':
            System.out.println('a');
            break;
        case 'b':
            System.out.println('b');
            break;
        default:
            break;
        }
    }
}

編譯後的程式碼如下: `public class switchDemoChar

public class switchDemoChar
{
    public switchDemoChar()
    {
    }
    public static void main(String args[])
    {
        char a = 'b';
        switch(a)
        {
        case 97: // 'a'
            System.out.println('a');
            break;
        case 98: // 'b'
            System.out.println('b');
            break;
        }
  }
}

透過以上的程式碼作比較我們發現:對char型別進行比較的時候,實際上比較的是ascii碼,編譯器會把char型變數轉換成對應的int型變數

三、switch對字串支援的實現

還是先上程式碼:

public class switchDemoString {
    public static void main(String[] args) {
        String str = "world";
        switch (str) {
        case "hello":
            System.out.println("hello");
            break;
        case "world":
            System.out.println("world");
            break;
        default:
            break;
        }
    }
}

對程式碼進行反編譯:

public class switchDemoString
{
    public switchDemoString()
    {
    }
    public static void main(String args[])
    {
        String str = "world";
        String s;
        switch((s = str).hashCode())
        {
        default:
            break;
        case 99162322:
            if(s.equals("hello"))
                System.out.println("hello");
            break;
        case 113318802:
            if(s.equals("world"))
                System.out.println("world");
            break;
        }
    }
}

看到這個程式碼,你知道原來字串的switch是透過equals()hashCode()方法來實現的。記住,switch中只能使用整型,比如byteshortchar(ackii碼是整型)以及int。還好hashCode()方法返回的是int,而不是long。透過這個很容易記住hashCode返回的是int這個事實。仔細看下可以發現,進行switch的實際是雜湊值,然後透過使用equals方法比較進行安全檢查,這個檢查是必要的,因為雜湊可能會發生碰撞。因此它的效能是不如使用列舉進行switch或者使用純整數常量,但這也不是很差。因為Java編譯器只增加了一個equals方法,如果你比較的是字串字面量的話會非常快,比如”abc” ==”abc”。如果你把hashCode()方法的呼叫也考慮進來了,那麼還會再多一次的呼叫開銷,因為字串一旦建立了,它就會把雜湊值快取起來。因此如果這個switch語句是用在一個迴圈裡的,比如逐項處理某個值,或者遊戲引擎迴圈地渲染螢幕,這裡hashCode()方法的呼叫開銷其實不會很大。

好,以上就是關於switch對整型、字元型、和字串型的支援的實現方式,總結一下我們可以發現,其實switch只支援一種資料型別,那就是整型,其他資料型別都是轉換成整型之後在使用switch的。

JDK | Switch對String的支援

java1.7版本之後,switch條件支援字串

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章