设有两个整数变量x与y
x ^= y;
y ^= x;
x ^= y;
能成功交换x与y的值。
为什么将上面的式子改成
x ^= y ^= x ^= y
不能成功交换?
甚至
y ^= x ^= y;
x ^= y;
也能实现。
设有两个整数变量x与y
x ^= y;
y ^= x;
x ^= y;
能成功交换x与y的值。
为什么将上面的式子改成
x ^= y ^= x ^= y
不能成功交换?
甚至
y ^= x ^= y;
x ^= y;
也能实现。
java的编译规则赋值优化。举个例子
a = 10;
a = 20;
连续的两次赋值,且中间没发现对a的读取,那么java编译器在编译时会将第一个赋值删掉。
再回到这次的问题:
b ^= a ^= b; 在编译后的 class文件中,这一行应该是先将a 与 b 做一次 ^=,a的结果再与 b 做一次 ^=
看下class文件,的确如此:
现在我们把它们写成一行
其实可以看到,这个时候编译器已经告诉我们警告(第二个a是灰色)编译器认为这一行代码会被编译成
我们再来看看此时的 class 文件
通过编译后的文件,我们可以很清晰的知道为什么 执行完这一行,a = 0、b = 10,那么为什么编译器会这样执行呢?
这就回到刚开篇的赋值优化问题了, 对于 a ^= b,这对a是一次赋值的过程,也读取了一次a的值,但是 对于 a^= (b ^= a ^= b) 的外层 a ^= 操作来说,java编译器认为后边括号里的内容是一次赋值,且与a无关,所以 内部的一次 ^= 操作被编译器优化掉了。
事实上,a^= (b ^= a ^= b) 会被优化成如下代码: