HOWTO · Java
Java 中的异或运算符
使用 Java 的 ^ 运算符处理布尔值和整数异或,并了解经过验证的示例和常见陷阱。
本页内容
在 Java 中,^ 是 XOR(异或)运算符。当恰好一个条件应为真时,用它处理 boolean 值;需要按位异或时,用它处理整数。它不是幂运算符:Java 没有 ** 运算符。Java 语言规范定义了这两种 ^ 形式。
条件应使用布尔形式,位或掩码应使用整数形式。该运算符可用于当前 Java 版本;示例已在 OpenJDK 17.0.20.1 上运行,而准备工作参考了当前 JDK 26 的发行信息。
将 XOR 用于布尔值
对于两个布尔操作数,只有操作数不同时,XOR 才为 true。其真值表很简单:
| 左侧 | 右侧 | left ^ right |
|---|---|---|
false |
false |
false |
false |
true |
true |
true |
false |
true |
true |
true |
false |
与 && 和 || 不同,^ 会计算两个操作数。不要用它替代 value != null && value.isReady() 这样的短路保护:方法调用仍会执行。仅当同时计算两个布尔表达式是安全的,且规则是“恰好一个”时使用它。
这个已验证的示例同时展示布尔 XOR 和整数 XOR:
public class BooleanAndIntegerXor {
public static void main(String[] args) {
System.out.println(true ^ false);
System.out.println(true ^ true);
System.out.println(0b1100 ^ 0b1010);
}
}
输出:
true
false
6
前两行说明布尔规则。对于整数,0b1100 ^ 0b1010 的结果为 0b0110,即十进制的 6:只有输入位不同的位置,结果位才为 1。
将 XOR 用于整数和掩码
按位形式接受 byte、short、char、int 和 long 等整型基本类型。Java 会在运算前执行二元数值提升,因此涉及较小整型的表达式通常得到 int 结果。float 和 double 不能作为 XOR 操作数。只有目标类型确实需要时才进行强制转换;转换可能丢失位。
XOR 可用于切换选定的位。如果 flags 是整数,mask 标识要更改的位,flags ^ mask 会恰好翻转这些位。再次应用同一个掩码会恢复原始位,因为 x ^ y ^ y 等于 x。这种可逆性适用于受控的位操作,但不能代替更清晰的应用程序逻辑。
查找没有配对的一个值
当其他每个值恰好出现两次时,整数 XOR 的一个简洁用途是找到没有配对的值。相等的值会抵消,因为 x ^ x 为 0,而 0 ^ x 为 x。
public class UniqueNumberXor {
public static void main(String[] args) {
int unique = 0;
for (int value : new int[] {4, 9, 4}) {
unique ^= value;
}
System.out.println(unique);
}
}
输出:
9
这是一种对边界条件敏感的技巧,而不是通用的“查找唯一数字”算法。它只在有一个值未配对、其他所有值都恰好出现两次时有效。例如,若另一个值出现三次,它就无法识别唯一值。当出现规则不同,或还需要频率信息时,请选择计数方法。
在适用时优先选择清晰的替代方案
比较两个布尔值是否不等时,请使用 !=;它可能比 ^ 更直接地表达意图。使用 & 1 检查整数是奇数还是偶数:奇偶性运算是 AND,而不是 XOR。虽然用 XOR 交换两个变量是一个广为人知的技巧,但在 Java 中,临时变量或普通赋值更清晰,也可避免别名错误。
关键区别很简单:对于 boolean 值,^ 表示异或;对于整数,它表示按位 XOR。检查操作数类型,记住两个布尔侧都会被计算,并在依赖重复值抵消之前说明数据假设。