简体   繁体   中英

A simple Java code returns some unexpected result

The following simplest Java code returns some unexpected output. Let's look at it.

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);
    }
}

The code above displays the following output on the console.

x = 0; y = 15

How?

According to operator precedence it can be rewritten like this

x^=y; // 15 ^ 20 = 27, x = 27
y^=27; // 20 ^ 27 = 15, y = 15
x^=15; // 15 ^ 15 = 0, x = 0

You basically do x XOR x (because you apply your xor operation twice with the same operand (y)) and that results in 0.

Let's evaluate your expression step by step, in your case we have to do it from right to left to follow the precedence:

     x^=y^=x^=y; 
<=>  y^x^y^x 
<=> (y^y) ^ (x^x) 
<=> (0) ^ (0) 
<=>  0

XOR operates on the rules that 1 XOR 1 = 0 and 1 XOR 0 = 1 and 0 XOR 0 = 0

In case you thought ^= was power.

15 in binary = 01111 20 in binary = 10100

XOR returns true for each bit that appears in one or the other of its operands, but not both. It might help to work through a simpler example:

x = 1001
y = 1110

x ^= y => 0111
y ^= x ^= y => 1001
x ^= y ^= x ^= y = 0000

Notice that:

x <=> y ^= x ^= y

Which means that you're ultimately performing:

x ^= x

... which must be zero, based on the definition of XOR.

For completeness, here's a work-through using the provided values for x and y :

x = 0000 1111
y = 0001 1011

x ^= y = 0001 0100
y ^= x ^= y => 0000 1111
x ^= y ^= x ^= y => 0000 0000

I don't have an actual answer, but I don't think precedence is the problem. Adding brackets to clarify, same thing happens:

//   3   2   1
   x^=(y^=(x^=y));

What I would have expected out of this is something equivalent to:

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;

What I think in fact happens is that the initial values are used, which in effect means:

x0 = x;
y0 = y;
x = x0^y0^x0^y0; //0
y = y0^x0^y0;    //15

Problem is, I'm not sure where in the language specification I can find this. The closest I came was to:

15.7.2 Evaluate Operands before Operation

The Java programming language also guarantees that every operand of an operator (except the conditional operators &&, ||, and ? :) appears to be fully evaluated before any part of the operation itself is performed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM