¿Por qué esta afirmación no funciona en java x ^ = y ^ = x ^ = y;

int x=1; int y=2; x ^= y ^= x ^= y; 

Estoy esperando que los valores sean intercambiados. Pero da x = 0 y y = 1. cuando probé en lenguaje C, da el resultado correcto.

Su statement es más o menos equivalente a esta forma expandida:

 x = x ^ (y = y ^ (x = x ^ y)); 

A diferencia de C, en Java se garantiza que el operando izquierdo de un operador binario se evaluará antes que el operando derecho. La evaluación ocurre de la siguiente manera:

 x = x ^ (y = y ^ (x = x ^ y)) x = 1 ^ (y = 2 ^ (x = 1 ^ 2)) x = 1 ^ (y = 2 ^ (x = 3)) x = 1 ^ (y = 2 ^ 3) // x is set to 3 x = 1 ^ (y = 1) x = 1 ^ 1 // y is set to 1 x = 0 // x is set to 0 

Puede revertir el orden de los argumentos a cada expresión xor para que la asignación se realice antes de que la variable se evalúe nuevamente:

 x = (y = (x = x ^ y) ^ y) ^ x x = (y = (x = 1 ^ 2) ^ y) ^ x x = (y = (x = 3) ^ y) ^ xx = (y = 3 ^ y) ^ x // x is set to 3 x = (y = 3 ^ 2) ^ x x = (y = 1) ^ x x = 1 ^ x // y is set to 1 x = 1 ^ 3 x = 2 // x is set to 2 

Esta es una versión más compacta que también funciona:

 x = (y ^= x ^= y) ^ x; 

Pero esta es una manera verdaderamente horrible de intercambiar dos variables. Es una idea mucho mejor usar una variable temporal.

Mark es completamente correcto acerca de cómo se evalúa en Java. La razón es JLS §15.7.2. , Evaluar Operandos antes de la Operación, y §15.7 , que requiere evaluación de izquierda a derecha:

Es equivalente (por §15.26.2 , Operadores de Asignación de Compuestos) a:

 x = x ^ (y = y ^ (x = (x ^ y))); 

Evaluamos de izquierda a derecha, haciendo ambos operandos antes de la operación.

 x = 1 ^ (y = y ^ (x = (x ^ y))); // left of outer x = 1 ^ (y = 2 ^ (x = (x ^ y))); // left of middle x = 1 ^ (y = 2 ^ (x = (1 ^ y))); // left of inner x = 1 ^ (y = 2 ^ (x = (1 ^ 2))); // right of inner x = 1 ^ (y = 2 ^ (x = 3)); // inner xor (right inner assign) x = 1 ^ (y = 2 ^ 3); // inner assign (right middle xor) x = 1 ^ (y = 1); // middle xor (right middle assign) x = 1 ^ 1; // middle assign (right outer xor) x = 0; // outer xor (right outer assign) 

Tenga en cuenta que es un comportamiento indefinido en C, porque está modificando la misma variable dos veces entre puntos de secuencia.