Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
345 views
in Technique[技术] by (71.8m points)

java - Why swapping integer variable by XOR doesn't work in a single line?

I want to swap the value of two integer variables in java using the XOR operator.

This is my code:

int i = 24;
int j = 17;

i ^= j;
j ^= i;
i ^= j;

System.out.println("i : " + i + " j : " + j);

It will work fine but the following equivalent code doesn't work:

int i = 24;
int j = 17;

i ^= j ^= i ^= j;

System.out.println("i : " + i + " j : " + j);

Output is like this:

i : 0    j : 24

First variable is zero! What's wrong with Java?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

According to Java specification (Java 7 specification), Section 15.26.2 (page 529).

A compound assignment expression of the form E1 op= E2 is equivalent to E1 = (T) ((E1) op (E2)), where T is the type of E1, except that E1 is evaluated only once.

According to Section 15.7 Evaluation Order (Page 423) (emphasis mine):

15.7 Evaluation Order

The Java programming language guarantees that the operands of operators appear to be evaluated in a specific evaluation order, namely, from left to right.

15.7.1 Evaluate Left-Hand Operand First

The left-hand operand of a binary operator appears to be fully evaluated before any part of the right-hand operand is evaluated.

If the operator is a compound-assignment operator (§15.26.2), then evaluation of the left-hand operand includes both remembering the variable that the left-hand operand denotes and fetching and saving that variable's value for use in the implied binary operation.

If evaluation of the left-hand operand of a binary operator completes abruptly, no part of the right-hand operand appears to have been evaluated.

Described in more details in Section 15.26.2 (page 529):

If the left-hand operand expression is not an array access expression, then:

? First, the left-hand operand is evaluated to produce a variable. [trimmed]

? Otherwise, the value of the left-hand operand is saved and then the right-hand operand is evaluated. [trimmed]

? Otherwise, the saved value of the left-hand variable and the value of the right-hand operand are used to perform the binary operation indicated by the compound assignment operator. [trimmed]

? Otherwise, the result of the binary operation is converted to the type of the left- hand variable, subjected to value set conversion (§5.1.13) to the appropriate standard value set (not an extended-exponent value set), and the result of the conversion is stored into the variable.

An example in the documentation

Example 15.26.2-2. Value Of Left-Hand Side Of Compound Assignment Is Saved Before Evaluation Of Right-Hand Side

  class Test {
      public static void main(String[] args) {
          int k = 1;
          int[] a = { 1 };
          k += (k = 4) * (k + 2);
          a[0] += (a[0] = 4) * (a[0] + 2);
          System.out.println("k==" + k + " and a[0]==" + a[0]);
      }
  }

So the expression in the question is re-written and grouped as:

i = i ^ (j = j ^ (i = i ^ j));

Left-hand operands are evaluated:

i = 24 ^ (j = 17 ^ (i = 24 ^ 17));
    **

Since the value of i is not "updated" as expected, it will cause the value of i to get 0 when 24 is swapped to j.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...