最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java運(yùn)算符易混點(diǎn)之&&、||、&、|與?到底差在哪詳解

 更新時(shí)間:2026年06月06日 07:25:38   作者:超級(jí)苦力怕  
這篇文章主要介紹了Java運(yùn)算符易混點(diǎn)之&&、||、&、|與?到底差在哪的相關(guān)資料,強(qiáng)調(diào)在條件判斷和位運(yùn)算場(chǎng)景下的正確使用法,并提供示例代碼幫助理解大家理解,需要的朋友可以參考下

前言

如果你經(jīng)常把 && 和 &、|| 和 | 記混,這篇從“條件判斷”和“二進(jìn)制位處理”兩個(gè)場(chǎng)景切開講,順著示例看會(huì)輕松很多。

一、先問一句:你在判斷條件,還是在處理二進(jìn)制位?

&&、||、&、| 長(zhǎng)得太像,所以最容易被混在一起記。真正的分界不是“一個(gè)符號(hào)還是兩個(gè)符號(hào)”,而是你現(xiàn)在想做什么:

  • 如果是在 ifwhile 里組合條件,通常要的是短路邏輯&&、||
  • 如果是在 boolean 表達(dá)式里強(qiáng)制兩邊都執(zhí)行,才會(huì)用非短路布爾運(yùn)算&、|^。
  • 如果操作的是整數(shù)、標(biāo)志位、掩碼、哈希、權(quán)限位,才是在做按位運(yùn)算&、|^、~<<、>>、>>>。

同一個(gè)符號(hào)在不同操作數(shù)類型下,含義會(huì)變:

運(yùn)算符操作數(shù)類型含義是否短路
&&boolean短路邏輯與是,左邊為 false 時(shí)右邊不執(zhí)行
||boolean短路邏輯或是,左邊為 true 時(shí)右邊不執(zhí)行
&boolean非短路邏輯與否,兩邊都會(huì)執(zhí)行
|boolean非短路邏輯或否,兩邊都會(huì)執(zhí)行
^boolean邏輯異或否,兩邊都會(huì)執(zhí)行
&整數(shù)類型按位與不屬于短路邏輯
|整數(shù)類型按位或不屬于短路邏輯
^整數(shù)類型按位異或不屬于短路邏輯
~整數(shù)類型按位取反不屬于短路邏輯

這里的“整數(shù)類型”包括 byteshort、char、intlong。其中 byteshort、char 參與位運(yùn)算時(shí)會(huì)先提升成 int

二、&&和||:短路的意義是“右邊可能不執(zhí)行”

&& 是短路邏輯與:左邊已經(jīng)是 false 時(shí),整個(gè)表達(dá)式一定是 false,右邊不會(huì)再算。

示例代碼(Java):短路與避免空指針

String s = null;

System.out.println(s != null && s.length() > 0); // false

這段代碼不會(huì)拋空指針異常,因?yàn)?s != null 已經(jīng)是 false,s.length() 根本不會(huì)執(zhí)行。

|| 是短路邏輯或:左邊已經(jīng)是 true 時(shí),整個(gè)表達(dá)式一定是 true,右邊不會(huì)再算。

示例代碼(Java):短路或跳過右側(cè)判斷

int score = 95;

if (score >= 90 || score == 100) {
    System.out.println("excellent");
}

這里 score >= 90 已經(jīng)為 true,后面的 score == 100 不需要再判斷。短路不是語(yǔ)法小優(yōu)化,而是很多保護(hù)性寫法成立的原因。

常見寫法:

示例代碼(Java):常見保護(hù)性判斷

if (user != null && user.isActive()) {
    // 先防 null,再訪問對(duì)象方法
}

if (list == null || list.isEmpty()) {
    // list 為 null 時(shí),不會(huì)繼續(xù)調(diào)用 isEmpty()
}

判斷條件時(shí),默認(rèn)選擇 &&、||。這不是因?yàn)樗鼈?ldquo;更高級(jí)”,而是它們更符合條件判斷的預(yù)期:前面的條件已經(jīng)能決定結(jié)果時(shí),后面的條件就不應(yīng)該再制造副作用或異常。

三、&和|放在 boolean 上:能用,但不短路

&、| 不只屬于位運(yùn)算。它們也可以作用在 boolean 上:

示例代碼(Java):boolean 上的非短路運(yùn)算

boolean a = false;
boolean b = true;

System.out.println(a & b); // false
System.out.println(a | b); // true

結(jié)果看起來和 &&、|| 很像,但執(zhí)行過程不一樣:&、| 會(huì)把左右兩邊都算完。

示例代碼(Java):?jiǎn)蝹€(gè) & 不會(huì)短路

String s = null;

System.out.println(s != null & s.length() > 0);

這段代碼會(huì)拋 NullPointerException。雖然左邊 s != nullfalse,但單個(gè) & 不短路,右邊的 s.length() 仍然會(huì)執(zhí)行。

| 也一樣:

示例代碼(Java):| 會(huì)執(zhí)行右側(cè)方法

static boolean logAndReturnTrue() {
    System.out.println("right side executed");
    return true;
}

public static void main(String[] args) {
    boolean left = true;

    System.out.println(left || logAndReturnTrue()); // 右邊不執(zhí)行
    System.out.println(left | logAndReturnTrue());  // 右邊會(huì)執(zhí)行
}

所以在普通條件判斷里,看到單個(gè) &、| 要先警惕:它可能不是作者想要的短路邏輯。

^ 放在 boolean 上表示邏輯異或:左右剛好一個(gè)為 true,結(jié)果才是 true

示例代碼(Java):boolean 異或

System.out.println(true ^ false); // true
System.out.println(true ^ true);  // false

它也不會(huì)短路,因?yàn)楫惢虮仨氈雷笥覂蛇叺闹挡拍芘袛?ldquo;是否不同”。

四、&、|、^、~放在整數(shù)上:逐位計(jì)算

位運(yùn)算不是在比較“整個(gè)數(shù)真不真”,而是在比較每一位二進(jìn)制。

1. 按位與&

對(duì)應(yīng)位都為 1,結(jié)果位才是 1。

示例代碼(Java):按位與

System.out.println(3 & 5); // 1

二進(jìn)制過程(text):3 & 5 的逐位結(jié)果

3  -> 0011
5  -> 0101
&     0001  -> 1

常見用途是檢查某一位是否存在

示例代碼(Java):用掩碼檢查權(quán)限位

int READ = 1;      // 0001
int WRITE = 1 << 1; // 0010

int permission = READ | WRITE;

boolean canRead = (permission & READ) != 0;

注意括號(hào)不能省。!= 的優(yōu)先級(jí)高于 &,如果寫成 permission & READ != 0,會(huì)先算 READ != 0,表達(dá)式就變成 int & boolean,直接編譯失敗。

2. 按位或|

對(duì)應(yīng)位只要有一個(gè)是 1,結(jié)果位就是 1。

示例代碼(Java):按位或

System.out.println(6 | 2); // 6

二進(jìn)制過程(text):6 | 2 的逐位結(jié)果

6  -> 0110
2  -> 0010
|     0110  -> 6

常見用途是合并標(biāo)志位

示例代碼(Java):合并多個(gè)標(biāo)志位

int READ = 1;       // 0001
int WRITE = 1 << 1; // 0010
int EXEC = 1 << 2;  // 0100

int permission = READ | WRITE; // 同時(shí)擁有 READ 和 WRITE
permission = permission | EXEC;

3. 按位異或^

對(duì)應(yīng)位不同,結(jié)果位才是 1

示例代碼(Java):按位異或

System.out.println(5 ^ 9); // 12

二進(jìn)制過程(text):5 ^ 9 的逐位結(jié)果

5  -> 0101
9  -> 1001
^     1100  -> 12

異或常見于“切換某一位”的場(chǎng)景:同一位異或 1 會(huì)翻轉(zhuǎn),異或 0 會(huì)保持不變。

示例代碼(Java):用異或切換某一位

int flag = 0b0101;
int mask = 0b0001;

System.out.println(flag ^ mask); // 0b0100

4. 按位取反~

~ 會(huì)把每一位都翻轉(zhuǎn),01,10

示例代碼(Java):按位取反

System.out.println(~5); // -6

這個(gè)結(jié)果看起來反直覺,是因?yàn)?Java 的 int 使用 32 位二進(jìn)制補(bǔ)碼表示。對(duì)任意 int x,都有:

規(guī)律說明(text):按位取反和負(fù)數(shù)的關(guān)系

~x == -x - 1

所以 ~5 等于 -6。

五、移位運(yùn)算:移動(dòng)的是二進(jìn)制位

移位運(yùn)算只用于整數(shù)類型。

運(yùn)算符名稱高位或低位如何補(bǔ)
<<左移右側(cè)補(bǔ) 0
>>有符號(hào)右移左側(cè)補(bǔ)符號(hào)位,正數(shù)補(bǔ) 0,負(fù)數(shù)補(bǔ) 1
>>>無(wú)符號(hào)右移左側(cè)一律補(bǔ) 0

左移常能看成乘以 2 的若干次方:

示例代碼(Java):左移兩位

System.out.println(5 << 2); // 20

二進(jìn)制過程(text):左移后的位變化

0000 0101  ->  0001 0100

右移要更謹(jǐn)慎。對(duì)非負(fù)數(shù),>> n 通常像除以 2^n

示例代碼(Java):非負(fù)數(shù)右移

System.out.println(15 >> 2); // 3

但對(duì)負(fù)數(shù),不要簡(jiǎn)單等同于 /。Java 的整數(shù)除法向 0 截?cái)?,?>> 會(huì)保留符號(hào)位:

示例代碼(Java):負(fù)數(shù)右移和整數(shù)除法的差異

System.out.println(-5 / 2);  // -2
System.out.println(-5 >> 1); // -3

>>> 不保留符號(hào)位,左側(cè)永遠(yuǎn)補(bǔ) 0。因此負(fù)數(shù)無(wú)符號(hào)右移后,常會(huì)變成很大的正數(shù):

示例代碼(Java):有符號(hào)右移和無(wú)符號(hào)右移

System.out.println(-6 >> 3);  // -1
System.out.println(-6 >>> 3); // 536870911

初學(xué)階段不要為了“看起來更底層”而用移位替代乘除。只有在處理掩碼、哈希、編碼、底層協(xié)議、集合源碼這類明確依賴二進(jìn)制布局的場(chǎng)景里,移位才是自然表達(dá)。

六、優(yōu)先級(jí):能加括號(hào)就別考驗(yàn)讀者

邏輯運(yùn)算和位運(yùn)算的優(yōu)先級(jí)大致可以記成:

優(yōu)先級(jí)速查(text):邏輯與位運(yùn)算從高到低

~、!                  // 一元運(yùn)算,優(yōu)先級(jí)高
<<、>>、>>>            // 移位
<、<=、>、>=           // 關(guān)系比較
==、!=                // 相等比較
&                     // 按位與 / 非短路邏輯與
^                     // 異或
|                     // 按位或 / 非短路邏輯或
&&                    // 短路邏輯與
||                    // 短路邏輯或

這能解釋一些表達(dá)式為什么能按預(yù)期運(yùn)行:

示例代碼(Java):不寫括號(hào)時(shí)的表達(dá)式

boolean result = x < y && !z;

它等價(jià)于:

示例代碼(Java):加括號(hào)后的等價(jià)表達(dá)式

boolean result = (x < y) && (!z);

但工程代碼里,不建議把優(yōu)先級(jí)當(dāng)成炫技空間。尤其是位運(yùn)算和比較混在一起時(shí),括號(hào)會(huì)讓語(yǔ)義清楚很多:

示例代碼(Java):位運(yùn)算和比較混用時(shí)加括號(hào)

boolean hasRead = (permission & READ) != 0;
int combined = READ | WRITE | EXEC;
int thirdBit = value & (1 << 2);

判斷規(guī)則很簡(jiǎn)單:如果讀者需要停下來回憶優(yōu)先級(jí)表,括號(hào)就應(yīng)該出現(xiàn)。

七、實(shí)戰(zhàn)判斷口訣

遇到 &&、||、&|、^~、移位運(yùn)算時(shí),可以按這幾個(gè)問題判斷:

  1. 是不是條件判斷?
    • 是:優(yōu)先使用 &&、||。
  2. 右邊是否可能有空指針、數(shù)組越界、方法副作用?
    • 是:更要使用短路邏輯。
  3. 操作數(shù)是不是整數(shù),而且你關(guān)心的是二進(jìn)制的某一位?
    • 是:使用位運(yùn)算。
  4. 是不是要表示權(quán)限、狀態(tài)、掩碼、哈希擾動(dòng)、編碼解碼?
    • 是:位運(yùn)算可能合適。
  5. 只是想把兩個(gè) boolean 條件連起來?
    • 不要隨手寫單個(gè) &|。

最容易記錯(cuò)的一句話是:

記憶口訣(text):一句話區(qū)分短路邏輯和位運(yùn)算

短路邏輯看“要不要繼續(xù)算”,位運(yùn)算看“每一位怎么算”。

&&、|| 解決的是控制流問題;&|、^、~、<<、>>>>> 解決的是二進(jìn)制表示問題。把這個(gè)邊界立住,空指針保護(hù)、條件副作用、權(quán)限掩碼和移位計(jì)算就不會(huì)混成一團(tuán)。

到此這篇關(guān)于Java運(yùn)算符易混點(diǎn)之&amp;&amp;、||、&amp;、|與 到底差在哪的文章就介紹到這了,更多相關(guān)Java運(yùn)算符&amp;&amp;、||、&amp;、|與位運(yùn)算內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java發(fā)送http get請(qǐng)求的兩種方式

    java發(fā)送http get請(qǐng)求的兩種方式

    這篇文章主要為大家詳細(xì)介紹了java發(fā)送http get請(qǐng)求的兩種方式,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • SpringCloud服務(wù)之間Feign調(diào)用不會(huì)帶上請(qǐng)求頭header的解決方法

    SpringCloud服務(wù)之間Feign調(diào)用不會(huì)帶上請(qǐng)求頭header的解決方法

    在Spring?Cloud中,使用Feign進(jìn)行服務(wù)之間的調(diào)用時(shí),默認(rèn)情況下是不會(huì)傳遞header的,這篇文章給大家介紹SpringCloud服務(wù)之間Feign調(diào)用不會(huì)帶上請(qǐng)求頭header的解決方法,感興趣的朋友一起看看吧
    2024-01-01
  • Java實(shí)現(xiàn)線程的四種方式解析

    Java實(shí)現(xiàn)線程的四種方式解析

    這篇文章主要介紹了Java實(shí)現(xiàn)線程的四種方式解析,線程是進(jìn)程中的一個(gè)執(zhí)行單元,負(fù)責(zé)當(dāng)前進(jìn)程中程序的執(zhí)行,一個(gè)進(jìn)程中至少有一個(gè)線程,一個(gè)進(jìn)程中是可以有多個(gè)線程的,這個(gè)應(yīng)用程序也可以稱之為多線程程序,需要的朋友可以參考下
    2023-10-10
  • @Transactional和@DS怎樣在事務(wù)中切換數(shù)據(jù)源

    @Transactional和@DS怎樣在事務(wù)中切換數(shù)據(jù)源

    這篇文章主要介紹了@Transactional和@DS怎樣在事務(wù)中切換數(shù)據(jù)源問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • OpenFeign實(shí)現(xiàn)遠(yuǎn)程調(diào)用

    OpenFeign實(shí)現(xiàn)遠(yuǎn)程調(diào)用

    這篇文章主要為大家詳細(xì)介紹了OpenFeign實(shí)現(xiàn)遠(yuǎn)程調(diào)用,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • java中兩個(gè)字符串的拼接、整數(shù)相加和浮點(diǎn)數(shù)相加實(shí)現(xiàn)代碼

    java中兩個(gè)字符串的拼接、整數(shù)相加和浮點(diǎn)數(shù)相加實(shí)現(xiàn)代碼

    這篇文章主要為大家介紹java中從鍵盤讀取用戶輸入兩個(gè)字符串,實(shí)現(xiàn)這兩個(gè)字符串的拼接、整數(shù)相加和浮點(diǎn)數(shù)相加,并輸出結(jié)果,需要的朋友可以參考下
    2021-05-05
  • Java中throw和throws異常處理完整例子說明

    Java中throw和throws異常處理完整例子說明

    這篇文章主要給大家介紹了關(guān)于Java中throw和throws異常處理的相關(guān)資料, throw關(guān)鍵字是用于在方法內(nèi)拋出異常,而throws關(guān)鍵字是在方法聲明中指定可能拋出的異常,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-06-06
  • springboot啟動(dòng)時(shí)如何獲取端口和項(xiàng)目名

    springboot啟動(dòng)時(shí)如何獲取端口和項(xiàng)目名

    這篇文章主要介紹了springboot啟動(dòng)時(shí)如何獲取端口和項(xiàng)目名,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • 超實(shí)用的Java快捷鍵(總結(jié))

    超實(shí)用的Java快捷鍵(總結(jié))

    下面小編就為大家?guī)硪黄瑢?shí)用的Java快捷鍵(總結(jié))。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-05-05
  • 基于java的opencv開發(fā)過程詳解

    基于java的opencv開發(fā)過程詳解

    這篇文章主要介紹了基于java的opencv開發(fā)過程詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-04-04

最新評(píng)論

乐业县| 天祝| 嘉定区| 徐闻县| 汤阴县| 鹰潭市| 江西省| 赤城县| 武鸣县| 文水县| 中江县| 台安县| 湛江市| 西贡区| 祁阳县| 环江| 永仁县| 新干县| 清镇市| 沙湾县| 象州县| 吉林省| 达孜县| 高邮市| 新建县| 佳木斯市| 花垣县| 泸溪县| 信丰县| 乌海市| 台南市| 宁强县| 汉寿县| 肇源县| 乳源| 莎车县| 河间市| 剑阁县| 高要市| 句容市| 沾化县|