日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
為什么switch里的case沒(méi)有break不行

 前言

一個(gè)小姐姐拿著一個(gè)switch的選擇題來(lái)問(wèn)我。

成都創(chuàng)新互聯(lián)公司,為您提供成都網(wǎng)站建設(shè)、重慶網(wǎng)站制作、網(wǎng)站營(yíng)銷推廣、網(wǎng)站開(kāi)發(fā)設(shè)計(jì),對(duì)服務(wù)汽車玻璃修復(fù)等多個(gè)行業(yè)擁有豐富的網(wǎng)站建設(shè)及推廣經(jīng)驗(yàn)。成都創(chuàng)新互聯(lián)公司網(wǎng)站建設(shè)公司成立于2013年,提供專業(yè)網(wǎng)站制作報(bào)價(jià)服務(wù),我們深知市場(chǎng)的競(jìng)爭(zhēng)激烈,認(rèn)真對(duì)待每位客戶,為客戶提供賞心悅目的作品。 與客戶共同發(fā)展進(jìn)步,是我們永遠(yuǎn)的責(zé)任!

之所以這么篤定地回答這個(gè)問(wèn)題,并不是我知道其中原理,而是之前在一個(gè)群里,有人問(wèn)了同類型的問(wèn)題,我瞥了一眼記住了答案,所以才依葫蘆畫(huà)瓢。

小姐姐接著問(wèn)我為什么,我說(shuō)少個(gè)break,但凡再問(wèn)一句:為什么少個(gè)break結(jié)果就不一樣,我就回答不出來(lái)了。所以,為了將尷尬扼殺于搖籃,還是研究一下break在switch的作用。

 從字節(jié)碼出發(fā)

按照慣例,先寫(xiě)demo表述問(wèn)題。 

 
 
 
 
  1. public static void main(String[] args) {  
  2.    int i = 0;  
  3.    switch (i) {  
  4.        case 0:  
  5.            System.out.println(0);  
  6.        case 1:  
  7.            System.out.println(1);  
  8.        case 2:  
  9.            System.out.println(2);  
  10.  } 

運(yùn)行代碼,結(jié)果如下:

*明明只匹配了case 0,為什么1和2也執(zhí)行了? 很費(fèi)解!按照慣用套路,看看字節(jié)碼能不能給個(gè)答案。

javac編譯和javap查看:

「tableswitch」和「lookupswitch」都用于switch條件跳轉(zhuǎn),前者用于case值連續(xù),例如上面代碼中的0、1、2;后者用于case值不連續(xù)。

從字節(jié)碼可以看出:switch中的case條件和對(duì)應(yīng)代碼塊是分開(kāi)的。如上圖,case為0時(shí),跳轉(zhuǎn)到標(biāo)號(hào)28代碼處;為1時(shí)跳轉(zhuǎn)到標(biāo)號(hào)35代碼處;為2時(shí)跳轉(zhuǎn)到標(biāo)號(hào)43代碼處;default則跳轉(zhuǎn)到標(biāo)號(hào)49代碼處。

這不,答案就出來(lái)了,當(dāng)case 0匹配了之后,直接跳轉(zhuǎn)到標(biāo)號(hào)28代碼處開(kāi)始執(zhí)行,輸出0,然后策馬奔騰,一路小下坡,順序執(zhí)行完后面所有代碼,直到標(biāo)號(hào)49 return,方法完執(zhí)行完成,程序結(jié)束。

如果按照正常的思維,是不是case 0匹配之后,跳到28,執(zhí)行完28、31、32輸出0之后,就應(yīng)該直接跳走,直接執(zhí)行49。那么,這個(gè)"跳走”用字節(jié)碼應(yīng)該怎么表示?

用return?那不行,因?yàn)閞eturn會(huì)結(jié)束方法,這樣switch后代碼也無(wú)法執(zhí)行。那怎么辦嘞.... 

關(guān)于goto

goto:無(wú)條件跳轉(zhuǎn),goto 1表示跳轉(zhuǎn)到標(biāo)號(hào)1的代碼處。

再寫(xiě)代碼樣例,這次在代碼中給每個(gè)case都加上break。 

 
 
 
 
  1. public static void main(String[] args) {  
  2.     int i = 0;  
  3.     switch (i) {  
  4.         case 0:  
  5.             System.out.println(0);  
  6.             break;  
  7.         case 10:  
  8.             System.out.println(1);  
  9.             break;  
  10.         case 2:  
  11.             System.out.println(2);  
  12.             break;  
  13.     }  
  14.     System.out.println("Hello World");  

重新編譯,再來(lái)看看字節(jié)碼。

如圖,與第一次的字節(jié)碼相比,在標(biāo)號(hào)35、45都有了goto指令。如果case 0匹配成功,則跳到標(biāo)號(hào)28執(zhí)行,執(zhí)行完代碼塊對(duì)應(yīng)的31、32指令之后,執(zhí)行35的goto指令跳轉(zhuǎn)到標(biāo)號(hào)55,這樣就跳出了switch作用范圍,case 1和2也不會(huì)被執(zhí)行。

等等,怎么少了一個(gè)goto,在標(biāo)號(hào)55的上方應(yīng)該還有一個(gè)goto才對(duì)!其實(shí)這就涉及到了編譯器優(yōu)化技術(shù),最后一個(gè)goto也是跳轉(zhuǎn)到標(biāo)號(hào)55的指令,但沒(méi)有g(shù)oto下一步也一樣順序執(zhí)行此行指令,所以這個(gè)goto被編譯器視為無(wú)用代碼進(jìn)行了消除。 

switch和if區(qū)別

先用if實(shí)現(xiàn)上面switch邏輯。 

 
 
 
 
  1. public static void main(String[] args) {  
  2.     int i = 0;  
  3.     if (i == 0) {  
  4.         System.out.println(0);  
  5.     } else if (i == 1) {  
  6.         System.out.println(1);  
  7.     } else if (i == 2) {  
  8.         System.out.println(2);  
  9.     }  

編譯成字節(jié)碼:

「if_icmpne」用于比較兩個(gè)int數(shù)。從字節(jié)碼也可以看出if和switch的區(qū)別:if條件和代碼塊的字節(jié)碼是順序的,switch條件和代碼塊是分開(kāi)的;if自動(dòng)生成goto指令,switch只有加了break才生成goto指令。 

結(jié)語(yǔ)

case中的break告訴前端編譯器:「給每個(gè)case對(duì)應(yīng)代碼塊的最后加上goto」。這樣,執(zhí)行完匹配上的代碼之后,就可以略過(guò)后面的case代碼塊了。

果然,求(xiao)知(jie)欲(jie)才是學(xué)習(xí)新知識(shí)的動(dòng)力。


當(dāng)前名稱:為什么switch里的case沒(méi)有break不行
文章起源:http://www.dlmjj.cn/article/djspeod.html