の原則の完全な理解を達成するためのJavaスイッチ

Javaの公式文書では説明しています。

スイッチは、バイト、ショート、CHAR、およびint型のプリミティブデータ型で動作します。また、列挙型、Stringクラス、およびいくつかの特別なクラスで動作するラップ特定のプリミティブ型:文字、バイト、ショート、整数

基本データ型でのバイト/文字

public class SwitchBasicTest {
    
    private int switchByte(byte i) {
        int ret;
        switch (i) {
            case 0:
                ret = 10;
                break;
            case 1:
                ret = 11;
                break;
            default:
                ret = 0;
        }

        return ret;
    }
    private int switchChar(char i) {
        int ret;
        switch (i) {
            case 0:
                ret = 10;
                break;
            case 1:
                ret = 11;
                break;
            case 'a':
                ret = 20;
                break;
            case '写':
                ret = 21;
                break;
            default:
                ret = 0;
        }

        return ret;
    }
}
复制代码

javap -vまたは逆コンパイルするために他のツールを使用してSwitchBasicTest.class本明細書で使用されるように、IDEAプラグインjclasslib Bytecode viewer

逆コンパイル入手switchByte方法バイトコード:

 0 iload_1
 1 lookupswitch 2
        0:  28 (+27)
        1:  34 (+33)
        default:  40 (+39)
28 bipush 10
30 istore_2
31 goto 42 (+11)
34 bipush 11
36 istore_2
37 goto 42 (+5)
40 iconst_0
41 istore_2
42 iload_2
43 ireturn

复制代码

switchChar メソッドのバイトコード:

 0 iload_1
 1 lookupswitch 4
        0:  44 (+43)
        1:  50 (+49)
        97:  56 (+55)
        20889:  62 (+61)
        default:  68 (+67)
44 bipush 10
46 istore_2
47 goto 70 (+23)
50 bipush 11
52 istore_2
53 goto 70 (+17)
56 bipush 20
58 istore_2
59 goto 70 (+11)
62 bipush 21
64 istore_2
65 goto 70 (+5)
68 iconst_0
69 istore_2
70 iload_2
71 ireturn

复制代码

それがために知られているbyte他の基本的なデータ型、switch直接使用する整数の比較

  • バイト、short値は直接全体転送することができます
  • チャーは、かかるunicodeコード値整数
  • 整数およびその他の包装タイプ、コールintValue整数変数の値を得る方法を

文字列(バージョンJDK1.7以降)の役割の中で

public class SwitchBasicTest {
    private int switchString(String i) {
            int ret;
            switch (i) {
                case "0":
                    ret = 10;
                    break;
                case "1":
                    ret = 11;
                    break;
                case "a":
                    ret = 20;
                    break;
                default:
                    ret = 0;
            }
    
            return ret;
        }
}
复制代码

使用IDEAエディタ、.classファイルは、コード逆コンパイルを参照のファイルを開きます。

public class SwitchBasicTest {
    private int switchString(String i) {
        byte var4 = -1;
        switch(i.hashCode()) {
        case 48:
            if (i.equals("0")) {
                var4 = 0;
            }
            break;
        case 49:
            if (i.equals("1")) {
                var4 = 1;
            }
            break;
        case 97:
            if (i.equals("a")) {
                var4 = 2;
            }
        }

        byte ret;
        switch(var4) {
        case 0:
            ret = 10;
            break;
        case 1:
            ret = 11;
            break;
        case 2:
            ret = 20;
            break;
        default:
            ret = 0;
        }

        return ret;
    }
}
复制代码

得られコンパイルswitchStringバイトコードを:

  0 aload_1
  1 astore_3
  2 iconst_m1
  3 istore 4
  5 aload_3
  6 invokevirtual #8 <java/lang/String.hashCode>
  9 lookupswitch 3
        48:  44 (+35)
        49:  59 (+50)
        97:  74 (+65)
        default:  86 (+77)
 44 aload_3
 45 ldc #9 <0>
 47 invokevirtual #10 <java/lang/String.equals>
 50 ifeq 86 (+36)
 53 iconst_0
 54 istore 4
 56 goto 86 (+30)
 59 aload_3
 60 ldc #11 <1>
 62 invokevirtual #10 <java/lang/String.equals>
 65 ifeq 86 (+21)
 68 iconst_1
 69 istore 4
 71 goto 86 (+15)
 74 aload_3
 75 ldc #12 <a>
 77 invokevirtual #10 <java/lang/String.equals>
 80 ifeq 86 (+6)
 83 iconst_2
 84 istore 4
 86 iload 4
 88 tableswitch 0 to 2	
        0:  116 (+28)
        1:  122 (+34)
        2:  128 (+40)
        default:  134 (+46)
116 bipush 10
118 istore_2
119 goto 136 (+17)
122 bipush 11
124 istore_2
125 goto 136 (+11)
128 bipush 20
130 istore_2
131 goto 136 (+5)
134 iconst_0
135 istore_2
136 iload_2
137 ireturn
复制代码

私たちは見ることができるswitchという効果をString整数のための2つに分割最終switch文、具体的な手順:

  • 計算と比較したハッシュコード
  • 同じハッシュコード、それがさらに使用されている場合equals、同じ文字列の内容を決定するために、二つの文字列のハッシュコードと同じ場合に処理

列挙の下で働きます

public enum SeasonEnum {
    SPRING, SUMMER, AUTUMN, WINTER
}

public class SwitchEnumTest {
   
    private static int testSpring(SeasonEnum seasonEnum) {
        int ret;
        switch (seasonEnum) {
            case AUTUMN:
                ret = 1;
                break;
            case SPRING:
                ret = 2;
                break;
            case SUMMER:
                ret = 3;
                break;
            case WINTER:
                ret = 4;
                break;
            default:
                ret = 5;
        }
        return ret;
    }
}
复制代码

逆コンパイル入手testSpring方法バイトコード:

 0 getstatic #6 <xx/SwitchEnumTest$1.$SwitchMap$xx$enumt$SeasonEnum>
 3 aload_0
 4 invokevirtual #7 <xx/enumt/SeasonEnum.ordinal>
 7 iaload
 8 tableswitch 1 to 4	1:  40 (+32)
        2:  45 (+37)
        3:  50 (+42)
        4:  55 (+47)
        default:  60 (+52)
40 iconst_1
41 istore_1
42 goto 62 (+20)
45 iconst_2
46 istore_1
47 goto 62 (+15)
50 iconst_3
51 istore_1
52 goto 62 (+10)
55 iconst_4
56 istore_1
57 goto 62 (+5)
60 iconst_5
61 istore_1
62 iload_1
63 ireturn
复制代码

あなたは見ることができます: 4 invokevirtual #7 <xx/enumt/SeasonEnum.ordinal>

つまり、switch列挙に作用するとき、列挙が呼び出すordinalメソッドをその最終的にint値比較

lookupswitch和tableswitch

  • tableswitch 配列を使用すること添字のジャンプ先線で位置決めすることができます
  • lookupswitch キーと値との関係を維持するために、行数、であることがマッチを見つけるためにインデックスを比較することにより、一つのジャンプ
  • tableswitchよりlookupswitch優れた検索のパフォーマンス
  • switchステートメントcase分岐条件値スパース、tableswitch空間低使用手順は、この場合に使用することができるlookupswitch命令

結論

  • switch 構文は、実際には整数パラメータに対してのみ有効です
  • breakバイトコードレベルで生成goto文をcaseテープずにbreak次回に直接case論理
  • switch列挙に作用する実際の列挙使用するordinal比較のための基礎として、メソッド戻り値
  • switch文字列場合、文字列に作用するhashcode比較の基準としては、hashcode同じがさらに使用されるequals文字列の内容を比較します
  • Java仮想マシン仕様、Java仮想マシンtableswitchlookupswitchの命令が唯一のint型の条件をサポートし、それがswitchサポートしていないlongロング

情報リファレンス

おすすめ

転載: juejin.im/post/5e8d8b62e51d4546ca30ad43