Java中短路運(yùn)算符與邏輯運(yùn)算符示例詳解
1、邏輯運(yùn)算符(部分)
| 符號(hào) | 名稱 |
|---|---|
| && | 短路與運(yùn)算符 |
| || | 短路或運(yùn)算符 |
| & | 與運(yùn)算符 |
| | | 或運(yùn)算符 |
對(duì)于理工科學(xué)習(xí)者來(lái)說(shuō),邏輯運(yùn)算是較為基礎(chǔ)的概念,通常會(huì)在大一的離散數(shù)學(xué)課程中有所了解。在Java以及更多C-Like語(yǔ)言中,&和|會(huì)分別表示邏輯運(yùn)算中的與、或,他們的運(yùn)算結(jié)果與我們?cè)跀?shù)學(xué)書(shū)中所學(xué)的邏輯運(yùn)算規(guī)則并無(wú)差異。但是,在實(shí)際編程的過(guò)程中,我們反而會(huì)更多使用&&和||,甚至不少同學(xué)都不了解&、|兩個(gè)運(yùn)算符。那么,這究竟是為什么呢?
2、短路運(yùn)算符
讓我們來(lái)回到最初學(xué)習(xí)邏輯運(yùn)算時(shí)解決問(wèn)題的真值表,以“或運(yùn)算”為例:
| a | b | 結(jié)果 |
|---|---|---|
| true | true | true |
| true | false | true |
| false | true | true |
| false | false | false |
a和b中,只要至少有一個(gè)為true,最終輸出的結(jié)果則為true。那么,從算法優(yōu)化的角度來(lái)思考問(wèn)題的話,我們?yōu)榱私?jīng)過(guò)最少步驟還能輸出可靠的結(jié)果,我們便可以把“或運(yùn)算”定義為,有一個(gè)true,就輸出true。
由此,“或運(yùn)算”可以被優(yōu)化為:從左向右,遇到有一個(gè)布爾表達(dá)式為true,則返回true,不進(jìn)行之后的運(yùn)算。
與之相似的,“與運(yùn)算”可以被優(yōu)化為:從左向右,遇到有一個(gè)布爾表達(dá)式為false,則返回false,不進(jìn)行之后的運(yùn)算。
故此,短路運(yùn)算符被設(shè)計(jì)了出來(lái)。但為了兼顧“執(zhí)行命令并返回”、“純粹的數(shù)學(xué)計(jì)算”等多種應(yīng)用場(chǎng)景,傳統(tǒng)的非短路邏輯運(yùn)算符也沒(méi)有被短路邏輯運(yùn)算符而取代。
此外,對(duì)于連寫(xiě)的短路運(yùn)算符,如func1()||func2()||func3()||func4(),編譯器也會(huì)為此優(yōu)化,我們不妨來(lái)閱讀這一部分的字節(jié)碼來(lái)驗(yàn)證這個(gè)結(jié)論:
public static void main(String[] args) {
boolean b1 = func1() || func2() || func3() || func4();
System.out.println("------------------");
boolean b2 = func1() | func2() | func3() | func4();
}
// func1() - func4() here
短路“或”的字節(jié)碼如下:
0: invokestatic #7 // Method func1:()Z 3: ifne 24 6: invokestatic #13 // Method func2:()Z 9: ifne 24 12: invokestatic #16 // Method func3:()Z 15: ifne 24 18: invokestatic #19 // Method func4:()Z 21: ifeq 28 24: iconst_1 25: goto 29 28: iconst_0 29: istore_1
3行、9行、15行的ifne是將棧頂元素與0(false)相比,如果不為false則跳轉(zhuǎn)到24行將常量1(true)入棧,完成賦值,會(huì)跳過(guò)其余的執(zhí)行。直到最后21行,才將最后方法結(jié)果的值再與0相比,如果還是0,則將常量0入棧,完成賦值。
普通“或”等字節(jié)碼如下:
38: invokestatic #7 // Method func1:()Z 41: invokestatic #13 // Method func2:()Z 44: ior 45: invokestatic #16 // Method func3:()Z 48: ior 49: invokestatic #19 // Method func4:()Z 52: ior 53: istore_2
則是普通的或運(yùn)算,無(wú)跳轉(zhuǎn),順序執(zhí)行最后賦值。
3、應(yīng)用與陷阱
在最起初,筆者重新認(rèn)識(shí)短路運(yùn)算符是在這樣一段代碼中:
public LoginCheckDTO XxxLoginCheck(String password) {
//some codes
if ( password == null || password.length() == 0 ) {
return LoginCheckDTO.EMPTY_PASSWORD;
}
//some codes
}
當(dāng)時(shí)筆者認(rèn)為,如果password為null,在嘗試調(diào)用password.length()時(shí),會(huì)拋出空指針異常,故此寫(xiě)法不好。但在后來(lái)進(jìn)行測(cè)試的時(shí)候,發(fā)現(xiàn)這樣寫(xiě)并沒(méi)有問(wèn)題,查閱相關(guān)資料便了解了短路運(yùn)算符的概念。
在這個(gè)例子中,當(dāng)執(zhí)行password == null返回true的時(shí)候,隨后的表達(dá)式將不會(huì)被執(zhí)行,就不存在拋出異常的情況了。這便是短路運(yùn)算符較為常用的一個(gè)應(yīng)用場(chǎng)景。
除此之外,我們還要警惕短路運(yùn)算符導(dǎo)致的指令執(zhí)行不完整。
譬如如下應(yīng)用場(chǎng)景,我們希望利用條件語(yǔ)句來(lái)判斷所有燈在上一狀態(tài)是否都開(kāi)著,并且無(wú)論如何我們希望最后打開(kāi)所有的燈。但是我們錯(cuò)誤使用了短路運(yùn)算符:
public boolean checkAndTurnOnAll() {
return checkAndTurnOn1() && checkAndTurnOn2();
}
private boolean checkAndTurnOn1() {
boolean check = check1();
turnOn1();
return check;
}
private boolean checkAndTurnOn2() {
boolean check = check2();
turnOn2();
return check;
}
在這個(gè)場(chǎng)景中,如果第一盞燈在上一個(gè)狀態(tài)是關(guān)閉狀態(tài),在checkAndTurnOn1()中雖然會(huì)執(zhí)行turnOn1(),并且返回false,但由于短路特性checkAndTurnOn2()并不會(huì)被執(zhí)行,所以最后期望的看到所有的燈都被打開(kāi)不一定會(huì)實(shí)現(xiàn)。這種情況應(yīng)當(dāng)使用&。
總結(jié)
到此這篇關(guān)于Java中短路運(yùn)算符與邏輯運(yùn)算符的文章就介紹到這了,更多相關(guān)Java短路運(yùn)算符與邏輯運(yùn)算符內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaWeb使用mvc模式實(shí)現(xiàn)登錄功能
本文主要介紹了JavaWeb使用mvc模式實(shí)現(xiàn)登錄功能,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01
Spring boot項(xiàng)目集成Camel FTP的方法示例
這篇文章主要介紹了Spring boot項(xiàng)目集成Camel FTP的方法示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-10-10
idea mac版打開(kāi)是出現(xiàn)打開(kāi)失敗問(wèn)題及解決
這篇文章主要介紹了idea mac版打開(kāi)是出現(xiàn)打開(kāi)失敗問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09
Java實(shí)現(xiàn)多個(gè)數(shù)組間的排列組合
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)多個(gè)數(shù)組間的排列組合,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-02-02

