日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

为什么switch里的case没有break不行

發(fā)布時間:2025/3/16 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 为什么switch里的case没有break不行 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前言

一個小姐姐拿著一個switch的選擇題來問我。

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

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

?

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

按照慣例,先寫demo表述問題。

?public?static?void?main(String[]?args)?{int?i?=?0;switch?(i)?{case?0:System.out.println(0);case?1:System.out.println(1);case?2:System.out.println(2);}

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

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

javac編譯和javap查看:

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

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

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

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

用return?那不行,因為return會結(jié)束方法,這樣switch后代碼也無法執(zhí)行。那怎么辦嘞....

?

關(guān)于goto

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

再寫代碼樣例,這次在代碼中給每個case都加上break。

??public?static?void?main(String[]?args)?{int?i?=?0;switch?(i)?{case?0:System.out.println(0);break;case?10:System.out.println(1);break;case?2:System.out.println(2);break;}System.out.println("Hello?World");}

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

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

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

?

switch和if區(qū)別

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

??public?static?void?main(String[]?args)?{int?i?=?0;if?(i?==?0)?{System.out.println(0);}?else?if?(i?==?1)?{System.out.println(1);}?else?if?(i?==?2)?{System.out.println(2);}}

編譯成字節(jié)碼:

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

?

結(jié)語

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

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

有道無術(shù),術(shù)可成;有術(shù)無道,止于術(shù)

歡迎大家關(guān)注Java之道公眾號

好文章,我在看??

總結(jié)

以上是生活随笔為你收集整理的为什么switch里的case没有break不行的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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