switch語句原理及易錯點

不加break會怎樣

觀察下面的代碼:
在這裏插入圖片描述
第一段代碼是最常見的寫法,也是最好的寫法,約定俗成的每個條件語句後添加break。如果因爲某種原因沒有寫break語句,沒有對此情況進行過探究的話,可能還真不知道第二、三段代碼會輸出什麼。

結論:如果不加break,程序從匹配成功的case語句開始,一直到遇見break語句或者執行完成所以條件語句塊後纔會跳出判斷,不管後面的case語句是否匹配成功都會執行語句塊中的代碼,也就是上面的第二、三段代碼。

有時候會故意缺省break語句來達到某種效果(例如幾種判斷都執行相同的代碼塊),不過這種情況極少,比如下面這個並沒有太大意義的例子,當檢測到當前月份是1、2、3、4月時都會輸出“現在是第一季度”:

switch (month){
    case 1:
    case 2:
    case 3:
    case 4:
        System.out.println("現在是第一季度");
        break;
    default:
        break;
}

switch語句的原理

根據經驗,當switch語句和if…else if…else語句可以實現相同功能(並且分支較多)時會盡量使用switch語句,因爲switch語句的效率更高。

if…else if…else語句的執行方式是順序執行所有判斷語句,直到滿足條件時執行語句代碼塊。

switch語句會維護一張跳轉表,不管case判斷語句的值是不是按照順序的,內存中的地址表都會按照順序進行排列。

switch語句會生成一個跳轉表來指示實際的case分支的地址,而這個跳轉表的索引號與switch變量的值是相等的。從而,switch-case不用像if-else if那樣遍歷條件分支直到命中條件,而只需訪問對應索引號的表項從而到達定位分支的目的。 具體地說,switch-case會生成一份表項數爲case量+1的跳錶,程序首先判斷switch變量是否大於(小於)最大(最小)case 常量,若大於(小於),則跳到default分支處理;否則取得索引號爲switch變量大小的跳錶項的地址(即跳錶的起始地址+表項大小*索引號),程序接着跳到此地址執行,到此完成了分支的跳轉。

case判斷的條件會有下面幾種情況,對應switch語句中的執行過程是不一樣的:
1、case條件的值是連續的,例如:case 1、case 2、case 3、case 4、case 5
  在switch中,編譯器多增加了一個數組用於存儲每個case對應的地址,根據switch中傳入的整數在數組中查到到對應的地址,直接通過這個地址跳轉到對應的位置。編譯器在處理switch時會首先校驗不滿足所有case的情況,當這種情況發生時代碼調轉到default或者switch語句塊之外。然後將傳入的整數值減一(數組元素是從0開始計數)。最後根據參數值找到應該跳轉的位置。
在這裏插入圖片描述
2、case條件的值不是連續的,例如:case 1、case 2、case 3、case 5
  去除掉上面的case 4條件後,仍會建立一個表,對應下圖中的關係。
在這裏插入圖片描述
3、case條件的值不是連續的,例如:case 1、case 2、case 5、case 6、case 256
  如果case條件間的值差異較大,則編譯器會採用索引表的方式來進行地址的跳轉,對應下圖中的關係。
在這裏插入圖片描述
如果想對內存進行深入研究的話可以編寫demo對內存進行跟蹤,下面這兩篇文章描述的也比較詳細:https://www.cnblogs.com/mukekeheart/p/10558167.html、https://www.jianshu.com/p/d382f653dd00

性能優化

  • 因爲if…else if…else語句會逐個條件進行判斷,直到命中,所以應將機率大的條件置於前面,這樣可以減少比較的次數
  • 如果分支較少,比如小於4個,或者case語句判斷的值跳躍較大時,沒必要使用switch語句
  • 編譯器是根據時間和空間的消耗來決定那種方式效率更高,所以在Switch寫判斷條件的時候最好做到連續緊密,可以最大限度的節省時間和內存

switch語句的注意事項

  • 當遇到 break 語句時,switch 纔會終止,控制流將跳轉到 switch 語句後的下一行
  • Java中的switch語句中表達式的值必須是整型、字符型、字符串類型(JDK7添加的新特性)和枚舉類型
    引申:case語句後常量表達式的值絕不可以是實數(有限小數、無限小數),例如case 1.1:即爲不合法語句
  • C++中的switch語句中表達式的值必須是整型、字符型和枚舉類型,不能是字符串類型
  • switch語句與其他控制語句的一個不同點:每個case中的多條語句加不加大括號均可
  • 最好在switch中添加default語句,用來處理異常情況
發佈了48 篇原創文章 · 獲贊 100 · 訪問量 26萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章