簡體   English   中英

&& (AND) 和 || (OR) 在 IF 語句中

[英]&& (AND) and || (OR) in IF statements

我有以下代碼:

if(!partialHits.get(req_nr).containsKey(z) || partialHits.get(req_nr).get(z) < tmpmap.get(z)){  
    partialHits.get(z).put(z, tmpmap.get(z));  
}

其中partialHits是一個 HashMap。
如果第一個陳述為真,會發生什么? Java 還會檢查第二個語句嗎? 因為為了讓第一條語句為真,HashMap 不應該包含給定的鍵,所以如果檢查第二條語句,我將得到NullPointerException
所以簡單來說,如果我們有以下代碼

if(a && b)  
if(a || b)

Java 會檢查b是否在第一種情況下a為假,如果a在第二種情況下為真?

不,它不會被評估。 這是非常有用的。 例如,如果您需要測試一個 String 是否不為 null 或為空,則可以編寫:

if (str != null && !str.isEmpty()) {
  doSomethingWith(str.charAt(0));
}

或者,反過來

if (str == null || str.isEmpty()) {
  complainAboutUnusableString();
} else {
  doSomethingWith(str.charAt(0));
}

如果我們在 Java 中沒有“短路”,我們就會在上面的代碼行中收到很多 NullPointerExceptions。

Java 有 5 種不同的布爾比較運算符:&、&&、|、||、^

& 和 && 是“與”運算符,| 和 || “或”運算符,^ 是“異或”

在檢查參數值之前,單個參數將檢查每個參數,而不管其值如何。 double 將首先檢查左參數及其值,如果為true ( || ) 或false ( && ) 則保持第二個參數不變。 聲音復雜? 一個簡單的例子應該清楚地說明:

給出所有示例:

 String aString = null;

和:

 if (aString != null & aString.equals("lala"))

在評估完成之前檢查這兩個參數,並且將為第二個參數拋出 NullPointerException。

 if (aString != null && aString.equals("lala"))

檢查第一個參數並返回false ,因此不會檢查第二個參數,因為無論如何結果都是false

OR 也一樣:

 if (aString == null | !aString.equals("lala"))

也會引發 NullPointerException。

 if (aString == null || !aString.equals("lala"))

檢查第一個參數並返回true ,因此不會檢查第二個參數,因為無論如何結果都是true

XOR 無法優化,因為它取決於兩個參數。

不,它不會被檢查。 這種行為稱為短路評估,是包括 Java 在內的許多語言的一個特性。

這里的所有答案都很好,但是,為了說明這是從哪里來的,對於這樣的問題,最好轉到源代碼:Java 語言規范。

第 15:23 節,條件與運算符 (&&)說:

&& 運算符類似於 &(第 15.22.2 節),但僅當其左側操作數的值為真時才計算其右側操作數。 [...] 在運行時,首先評估左側操作數表達式 [...] 如果結果值為 false,則條件和表達式的值為 false 且不評估右側操作數表達式. 如果左側操作數的值為真,則對右側表達式求值 [...] 結果值成為條件與表達式的值。 因此, && 在布爾操作數上計算與 & 相同的結果。 它的不同之處僅在於右側操作數表達式是有條件地而不是始終進行計算的。

同樣, 第 15:24 節,條件或運算符 (||)說:

|| 運算符就像 | (第 15.22.2 節),但僅當其左側操作數的值為 false 時才評估其右側操作數。 [...] 在運行時,首先評估左側操作數表達式; [...] 如果結果值為真,則條件或表達式的值為真,並且不計算右側操作數表達式。 如果左側操作數的值為假,則評估右側表達式; [...] 結果值成為條件或表達式的值。 因此,|| 計算與 | 相同的結果在布爾或布爾操作數上。 它的不同之處僅在於右側操作數表達式是有條件地而不是始終進行計算的。

可能有點重復,但最好確認它們的工作方式。 類似地,條件運算符 (?:) 只計算適當的“一半”(如果值為真則為左半,如果值為假則為右半),允許使用以下表達式:

int x = (y == null) ? 0 : y.getFoo();

沒有 NullPointerException。

這里的短路意味着不會評估第二個條件。

If ( A && B ) 如果 A 為 False 將導致短路。

If ( A && B ) 如果 A 為真,則不會導致短路。

If ( A || B ) 如果 A 為 True 將導致短路。

If ( A || B ) 如果 A 為假,則不會導致短路。

不,如果 a 為真(在 a or測試中),則不會測試 b,因為無論 b 表達式的值是什么,測試結果都將始終為真。

做一個簡單的測試:

if (true || ((String) null).equals("foobar")) {
    ...
}

不會拋出NullPointerException

不,它不會,一旦知道結果,Java 將短路並停止評估。

是的,布爾表達式的短路評估是所有類 C 家族的默認行為。

一個有趣的事實是 Java 也使用&| 作為邏輯操作數(它們是重載的,對於int類型,它們是預期的按位運算)來計算表達式中的所有項,這在您需要副作用時也很有用。

這又回到了&和&&的基本區別,| 和 ||

順便說一句,您多次執行相同的任務。 不確定效率是否是一個問題。 您可以刪除一些重復。

Z z2 = partialHits.get(req_nr).get(z); // assuming a value cannout be null.
Z z3 = tmpmap.get(z); // assuming z3 cannot be null.
if(z2 == null || z2 < z3){   
    partialHits.get(z).put(z, z3);   
} 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM