可以使用逻辑异或(^)实现int、long等基本整数类型的原地交换,依赖a^a=0和a^0=a恒等式;但不适用于BigInteger(不可变、不支持位运算符重载)和Integer(不可变、需拆箱装箱),且存在可读性差、未定义行为等缺陷,实际推荐用临时变量。

可以使用逻辑异或(^)实现两个整数变量的原地交换,但仅适用于 基本类型 int(或 long 等整数类型),且需满足特定前提。对“大型整数”需特别注意:若指 java.math.BigInteger,则 无法直接用 ^ 交换,因其不支持位运算符重载,且是不可变对象。
适用场景:基本整数类型(int、long)
异或交换依赖恒等式:a ^ a = 0 和 a ^ 0 = a,推导如下:
- a = a ^ b
- b = a ^ b → 即 (a^b) ^ b = a
- a = a ^ b → 即 (a^b) ^ a = b
代码示例:
int x = 123456; int y = 789012; x = x ^ y; y = x ^ y; // 此时 y 变为原 x x = x ^ y; // 此时 x 变为原 y
不适用场景:BigInteger 或包装类(Integer)
BigInteger 没有 ^ 运算符支持,也不能通过位运算修改其值(它是不可变的)。试图写 bigA = bigA.xor(bigB) 是合法的,但必须显式赋值,且无法用三步异或完成原地交换——因为每次调用 xor() 都返回新对象,仍需中间引用或额外变量来暂存。
同理,Integer 等包装类型是不可变的,且 ^ 操作会自动拆箱为 int,但交换后重新装箱会产生新对象,引用本身仍需更新,无法规避变量赋值操作。
为什么不能用于“大型”数值本身?
Java 的 int 最大为 2³¹−1,long 为 2⁶³−1,超出即溢出。所谓“大型整数”若指超过 long 范围的数,唯一选择是 BigInteger,而它不支持 ^ 作为中缀运算符,也没有就地修改能力。此时交换必须依赖临时变量(哪怕只是方法内局部引用),这是语言模型决定的,非技巧可绕过。
实际建议:优先使用临时变量
尽管异或交换在理论上避免了额外空间,但它:
– 可读性差,易引发维护困惑;
– 对相同变量操作(如 x ^= y ^= x ^= y)行为未定义(Java 不保证赋值顺序);
– 无法处理 null(对 Integer)或任意对象;
– 现代 JVM 优化极好,临时变量几乎无性能开销。
推荐写法:
int temp = x; x = y; y = temp;
简洁、安全、符合直觉。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











