下面最简单的Java代码返回一些意外的输出。让我们看看。
package interchange;
final public class Main
{
public static void main(String[] args)
{
int x = 15;
int y = 20;
x^=y^=x^=y;
System.out.println("x = " + x + "; y = " + y);
}
}
上面的代码在控制台上显示以下输出:
x = 0; y = 15
如何?
根据运算符的优先级,可以这样重写
x^=y; // 15 ^ 20 = 27, x = 27
y^=27; // 20 ^ 27 = 15, y = 15
x^=15; // 15 ^ 15 = 0, x = 0
您基本上执行x XOR x
(因为您对相同的操作数(y)应用了两次xor操作),结果为0。
让我们一步一步地计算你的表达式,在你的例子中,我们必须从右向左执行,以遵循优先级:
x^=y^=x^=y;
<=> y^x^y^x
<=> (y^y) ^ (x^x)
<=> (0) ^ (0)
<=> 0
XOR的操作规则为1 XOR 1 = 0和1 XOR 0 = 1和0 XOR 0 = 0
如果你认为^=是权力。
15 in binary = 01111
异或对出现在其中一个操作数中的每个位返回true,但不是两个操作数都返回true。通过一个更简单的例子可能会有所帮助:
x = 1001
y = 1110
x ^= y => 0111
y ^= x ^= y => 1001
x ^= y ^= x ^= y = 0000
注意:
x <=> y ^= x ^= y
这意味着你最终要执行:
x ^= x
…根据异或的定义,该值必须为零。
为完整起见,下面是使用x
和y
提供的值的操作:
x = 0000 1111
y = 0001 1011
x ^= y = 0001 0100
y ^= x ^= y => 0000 1111
x ^= y ^= x ^= y => 0000 0000
我没有一个实际的答案,但我不认为优先级是问题。添加括号来澄清,同样的事情发生:
// 3 2 1
x^=(y^=(x^=y));
我希望从这里得到的等价于:
x^=y; //1: xor x with y, update x, return the new x;
y^=x; //2: xor y with (result of 1), update y, return the new y;
x^=y; //3: xor x with (result of 2), update x, return the new x;
我认为实际情况是使用了初始值,这实际上意味着:
x0 = x;
y0 = y;
x = x0^y0^x0^y0; //0
y = y0^x0^y0; //15
问题是,我不确定在语言规范中我可以找到这个。最接近的是:
15.7.2
操作前求操作数Java编程语言还保证操作符的每个操作数(除了条件运算符&&、||和?:)似乎得到了充分的评估在操作本身的任何部分执行之前。