日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

java基础(六) switch语句的深入解析

發(fā)布時(shí)間:2025/3/20 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java基础(六) switch语句的深入解析 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

引言

??switch 語(yǔ)句是非常的基礎(chǔ)的知識(shí),掌握起來(lái)也不難掌握,語(yǔ)法比較簡(jiǎn)單。但大部分人基本是知其然,不知其所以然。譬如 早期JDK只允許switch的表達(dá)式的值 int及int類(lèi)型以下的基本類(lèi)型,后期的JDK卻允許匹配比較 字符串、枚舉類(lèi)型,這是怎么做到的呢?原理是什么?本文將深入去探索。

一、switch 介紹

switch 語(yǔ)法格式:

switch (表達(dá)式) {case 常量表達(dá)式或枚舉常量:語(yǔ)句;break;case 常量表達(dá)式或枚舉常量:語(yǔ)句;break;......default: 語(yǔ)句;break;}

switch 匹配的表達(dá)式可以是:

  • byte、short、char、int類(lèi)型及 這4種類(lèi)型的包裝類(lèi)型;
  • 枚舉類(lèi)型;
  • String 類(lèi)型;

case 匹配的表達(dá)式可以是:

  • 常量表達(dá)式;
  • 枚舉常量;

注意一點(diǎn): case提供了switch表達(dá)式的入口地址,一旦switch表達(dá)式與某個(gè)case分支匹配,則從該分支的語(yǔ)句開(kāi)始執(zhí)行,一直執(zhí)行下去,即其后的所有case分支的語(yǔ)句也會(huì)被執(zhí)行,直到遇到break語(yǔ)句。

看個(gè)例子體會(huì)一下:

public static void main(String[] args) {String s = "a";switch (s) {case "a": //a分支System.out.println("匹配成功1");case "b": //b分支System.out.println("匹配成功2");case "c": //c分支System.out.println("匹配成功3");break;case "d": //d分支System.out.println("匹配成功4");break;default:break;}}

運(yùn)行結(jié)果:

匹配成功1
匹配成功2
匹配成功3

??switch成功匹配了a分支,但a、b分支都沒(méi)有 break 語(yǔ)句,所以一直執(zhí)行a分支后的所有語(yǔ)句,直到遇到c分支的break語(yǔ)句才終止。

二、編譯器對(duì) switch 表達(dá)式的各種類(lèi)型的處理

??盡管 switch 支持的類(lèi)型擴(kuò)充了幾個(gè),但其實(shí)在底層中,swtich 只能支持4種基本類(lèi)型,其他幾個(gè)類(lèi)型是通過(guò)一些方式來(lái)間接處理的,下面便是講解編譯器對(duì)擴(kuò)充類(lèi)型的處理。

1、對(duì)包裝類(lèi)的處理

??對(duì)包裝類(lèi)的處理是最簡(jiǎn)單的 —— 拆箱。看下面的例子,switch 比較的是包裝類(lèi) Byte 。

Byte b = 2;switch (b) {case 1:System.out.println("匹配成功");break;case 2:System.out.println("匹配成功");break;}

用jad反編譯一下這段代碼,得到的代碼如下:

Byte b = Byte.valueOf((byte)2);switch(b.byteValue()){case 1: // '\001'System.out.println("\u5339\u914D\u6210\u529F");break;case 2: // '\002'System.out.println("\u5339\u914D\u6210\u529F");break;}

??反編譯的代碼很簡(jiǎn)單,底層的switch比較的是Byte通過(guò)(拆箱)方法byteValue()得到的byte值。順便說(shuō)一下,這段反編譯代碼不僅揭開(kāi)了 拆箱 的解析原理,也展示了 裝箱 的解析原理(第一句代碼);

2. 枚舉類(lèi)型

為了簡(jiǎn)單起見(jiàn),直接采用JDK提供的枚舉類(lèi)型的線程狀態(tài)類(lèi) Thread.state 類(lèi)。

Thread.State state = Thread.State.RUNNABLE;switch (state) {case NEW:System.out.println("線程處于創(chuàng)建狀態(tài)");break;case RUNNABLE:System.out.println("線程處于可運(yùn)行狀態(tài)");break;case TERMINATED:System.out.println("線程結(jié)束");break;default:break; }

反編譯代碼:

Sex sex = Sex.MALE;switch($SWITCH_TABLE$Test_2018_1_14$Sex()[sex.ordinal()]){case 1: // '\001'System.out.println("sex:male");break;case 2: // '\002'System.out.println("sex:female");break;}

??從編譯代碼中發(fā)現(xiàn),編譯器對(duì)于枚舉類(lèi)型的處理,是通過(guò)創(chuàng)建一個(gè)輔助數(shù)組來(lái)處理,這個(gè)數(shù)組是通過(guò)一個(gè)$SWITCH_TABLE$java$lang$Thread$State() 方法創(chuàng)建的,數(shù)組是一個(gè)int[]類(lèi)型數(shù)組,數(shù)組很簡(jiǎn)單,在每個(gè)枚舉常量的序號(hào)所對(duì)應(yīng)的數(shù)組下標(biāo)位置的賦一個(gè)值,按序號(hào)大小賦值,從1開(kāi)始遞增。 其代碼如下:

//int 數(shù)組 private static int $SWITCH_TABLE$java$lang$Thread$State[];//創(chuàng)建數(shù)組的方法 static int[] $SWITCH_TABLE$java$lang$Thread$State(){$SWITCH_TABLE$java$lang$Thread$State;if($SWITCH_TABLE$java$lang$Thread$State == null) goto _L2; else goto _L1 _L1:return; _L2:JVM INSTR pop ;int ai[] = new int[Thread.State.values().length];try{ai[Thread.State.BLOCKED.ordinal()] = 3;}catch(NoSuchFieldError _ex) { }try{ai[Thread.State.NEW.ordinal()] = 1;}catch(NoSuchFieldError _ex) { }try{ai[Thread.State.RUNNABLE.ordinal()] = 2;}catch(NoSuchFieldError _ex) { }try{ai[Thread.State.TERMINATED.ordinal()] = 6;}catch(NoSuchFieldError _ex) { }try{ai[Thread.State.TIMED_WAITING.ordinal()] = 5;}catch(NoSuchFieldError _ex) { }try{ai[Thread.State.WAITING.ordinal()] = 4;}catch(NoSuchFieldError _ex) { }return $SWITCH_TABLE$java$lang$Thread$State = ai;} }

3、 對(duì)String類(lèi)型的處理

依舊是先看個(gè)例子,再查看這個(gè)例子反編譯代碼,了解編譯器的是如何解析的。

public static void main(String[] args) {String s = "China";switch (s) {case "America": System.out.println("匹配到美國(guó)");break;case "China": System.out.println("匹配到中國(guó)");break;case "Japan": System.out.println("匹配到日本");default:break;}}

反編譯得到的代碼:

public static void main(String args[]){String s = "China";String s1;switch((s1 = s).hashCode()){default:break;case 65078583: if(s1.equals("China"))System.out.println("\u5339\u914D\u5230\u4E2D\u56FD");break;case 71341030: if(s1.equals("Japan"))System.out.println("\u5339\u914D\u5230\u65E5\u672C");break;case 775550446: if(s1.equals("America"))System.out.println("\u5339\u914D\u5230\u7F8E\u56FD");break;}}

??從反編譯的代碼可以看出,switch 的String變量、case 的String常量都變成對(duì)應(yīng)的字符串的 hash 值。也就是說(shuō),switch仍然沒(méi)有超出它的限制,只是通過(guò)使用 String對(duì)象的hash值來(lái)進(jìn)行匹配比較,從而支持 String 類(lèi)型。

總結(jié):

  • 底層的switc只能處理4個(gè)基本類(lèi)型的值。其他三種類(lèi)型需要通過(guò)其他方式間接處理,即轉(zhuǎn)成基本類(lèi)型來(lái)處理。
  • 編譯器對(duì)包裝類(lèi)的處理是通過(guò) 拆箱。
  • 對(duì)枚舉類(lèi)型的處理,是通過(guò)枚舉常量的序號(hào)及一個(gè)數(shù)組。
  • 對(duì)字符串String的處理,是通過(guò) String 的hash值。

作者:jinggod
出處:http://www.cnblogs.com/jinggod/p/8425260.html

總結(jié)

以上是生活随笔為你收集整理的java基础(六) switch语句的深入解析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。