Java 中 |(邏輯或)與 ||(條件或)同為布爾運算,但求值策略截然不同,直接影響帶副作用表達式的執行結果。同理 & 與 &&。
| 運算符 | 名稱 | 求值策略 | 右側表達式執行條件 |
|---|---|---|---|
|| | 條件或(短路或) | 左真則停,左假則繼續 | 左側為 false 時執行 |
| | 邏輯或(非短路) | 無論左右,皆完整求值 | **永遠執行** |
&& | 條件與(短路與) | 左假則停,左真則繼續 | 左側為 true 時執行 |
& | 邏輯與(非短路) | 無論左右,皆完整求值 | **永遠執行** |
// 案例 1:使用 ||(短路)
int a = 5, b = 10;
if (a > 4 || b++ > 10) {
System.out.println("a=" + a + ", b=" + b); // 輸出:a=5, b=10
}
// 解析:a>4 為 true,短路,b++ 不執行,b 保持 10
// 案例 2:使用 |(非短路)
int a = 5, b = 10;
if (a > 4 | b++ > 10) {
System.out.println("a=" + a + ", b=" + b); // 輸出:a=5, b=11
}
// 解析:雖然 a>4 為 true,但 | 強制求值右側,b++ 執行,b 變 11
當操作數為 int/long 等整數類型時,|、&、^ 為**位運算符**(按位或/與/異或),不具備短路特性,兩側均參與位運算。
int x = 3 | 5; // 011 | 101 = 111 → 7 int y = 3 & 5; // 011 & 101 = 001 → 1
||、&&):性能更好(避免無效計算),且符合直覺邏輯。if (initA() | initB()) 要求兩個初始化方法**都必須執行**。if (obj != null && obj.isValid()) 利用短路避免 NPE,| 會導致 NPE。|| 編譯為 ifne/ifeq 跳轉指令實現短路;| 編譯為 ior(int 或)或 lor(long 或)指令,無跳轉,雙操作數必須入棧。