异或能不借助临时变量交换两个整数,因其满足a^b^b==a的可逆性;但仅适用于同地址不同的整型变量,且生产环境不推荐使用。

为什么异或能不借助临时变量交换两个整数
因为 ^ 是可逆的位运算:对同一值连续异或两次,结果还原为原值。即 a ^ b ^ b == a(b ^ b 恒为 0,而 a ^ 0 == a)。这提供了“原地打转”的数学基础。
常见错误是误以为它适用于所有类型——只对整型(int、long 等)安全;浮点数、对象、null 都不能用。
使用场景很窄:仅限算法题炫技或嵌入式极简环境;生产代码中几乎从不出现,可读性差且无性能收益。
Java 中用 ^ 交换两个 int 变量的标准写法
必须严格按三步顺序执行,缺一不可,且不能用在同一个表达式里(否则依赖求值顺序,Java 不保证):
立即学习“Java免费学习笔记(深入)”;
a = a ^ b;-
b = a ^ b;(此时a已更新,等价于(a^b) ^ b → a) -
a = a ^ b;(此时b已是原a,等价于(a^b) ^ a → b)
错误示范:a ^= b ^= a ^= b; —— 这在 Java 中行为未定义,实际结果取决于编译器和 JVM 实现,多数情况下会把两个变量都变成 0。
交换失败的典型现象和原因
最常踩的坑是交换相同变量地址(即 a 和 b 引用同一个变量):
- 写成
swap(x, x);或在数组中写arr[i] = arr[i] ^ arr[i]; - 结果:该值变为 0(因为
x ^ x == 0),且无法恢复 - Java 中没有指针,但若传入同一数组下标(如
swap(arr[0], arr[0])),效果等同
另一个隐形陷阱:溢出不影响结果(异或与加减不同,不关心符号位进位),但若变量是 byte 或 short,Java 会自动提升为 int 运算,赋值时需强转,否则编译报错。
比异或更靠谱的交换方式有哪些
现代 JVM 下,异或交换没有任何性能优势——热点代码会被优化,而加减法或临时变量反而更易被寄存器分配优化。
推荐做法:
- 日常编码直接用临时变量:
int t = a; a = b; b = t;,语义清晰,JVM 友好 - 若真要省变量,且确定是
int,可用加减:a += b; b = a - b; a -= b;,但要注意溢出风险 - 泛型或对象交换?别想异或了,老实用
Collections.swap()或自己写带类型参数的方法
真正容易被忽略的是:这个技巧在多线程环境下完全不适用——三步操作不是原子的,中间状态可能被其他线程读到,而临时变量方案至少能配合 synchronized 封装。










