logical - string java operations
La asignación múltiple en una línea no funciona como se esperaba (3)
El orden de evaluación se define en el capítulo 15 de la JLS. El artículo 15.7.1 dice:
Si el operador es un operador de asignación compuesta (§15.26.2), la evaluación del operando de la izquierda incluye tanto recordar la variable que el operando de la izquierda denota como recuperar y guardar el valor de esa variable para usar en la operación binaria implícita .
Para explicar con más detalle, tienen dos ejemplos de cálculos que involucran asignaciones. Aquí la tarea está en la mano izquierda del operador:
int i = 2; int j = (i=3) * i; System.out.println(j);
Y específicamente dicen que el resultado es 9 y no se permite que sea 6. Es decir, tanto (i = 3) se calcula como 3 y a i se le asigna 3 antes de multiplicarse consigo mismo.
Pero en el segundo ejemplo:
int a = 9; a += (a = 3); // first example System.out.println(a); int b = 9; b = b + (b = 3); // second example System.out.println(b);
El JLS especifica que ambas impresiones deben producir 12, y no se les permite producir 6. Es decir, debido a que la asignación a b está en el lado derecho, el valor de la izquierda b
(o la izquierda implícita a
en la operación +=
) , el valor antes de esa asignación se recupera y se guarda primero, y solo entonces se realiza la operación dentro de los paréntesis.
Internamente, las expresiones se dividen en operaciones JVM que empujan y hacen estallar valores en una "pila de operandos". Si lo piensas así, en b = b + (b=3)
El valor de b
se coloca primero en la pila de operandos, luego se ejecuta (b = 3) y su valor se agrega al valor emergente de la pila (antiguo valor de b), tendrá sentido. En este punto, la mano izquierda b
solo significa "Lo que el valor de b era cuando se empujó en la pila" y no el "valor actual de b".
Estoy tratando de intercambiar dos int
s - x
y y
en el ejemplo, y hacerlo en una línea sin una función de biblioteca.
Así que empecé con esto:
int x = 4;
int y = 3;
System.out.println(x);
System.out.println(y);
x ^= y;
System.out.println(x);
System.out.println(y);
y ^= x;
System.out.println(x);
System.out.println(y);
x ^= y;
System.out.println(x);
System.out.println(y);
La salida fue 4, 3, 7, 3, 7, 4, 3, 4
como se esperaba. Todo bien hasta ahora.
El siguiente fue este:
int x = 4;
int y = 3;
System.out.println(x);
System.out.println(y);
y ^= (x ^= y);
System.out.println(x);
System.out.println(y);
x ^= y;
System.out.println(x);
System.out.println(y);
La salida fue 4, 3, 7, 4, 3, 4
como se esperaba una vez más. Todavía bien hasta ahora.
Entonces, finalmente, esto:
int x = 4;
int y = 3;
System.out.println(x);
System.out.println(y);
x ^= (y ^= (x ^= y));
System.out.println(x);
System.out.println(y);
En esta etapa la salida se convirtió en 4, 3, 0, 4
. Ahora sé que el 0
es el resultado de 4 ^ 4
porque la asignación x
no estaba completa en ese momento, ¿por qué sucede esto? ¿Por qué la x ^= y
realidad asigna 7
a la variable x
para que se convierta en 7 ^ 4
para la última asignación?
Intentemos expandir tu última expresión.
Se evalúa a,
x = x^(y = y^ (x = x^y));
Tenga en cuenta que las expresiones se evalúan de izquierda a derecha ,
se vuelve,
x = 4 ^ (y = 3 ^ (x = 4 ^ 3));
Ahora, el problema se ha vuelto obvio. ¿Derecha?
Editar:
Para aclarar la confusión, permítame tratar de explicar a qué me refiero al evaluar de izquierda a derecha.
int i = 1;
s = i + (i = 2) + i;
Ahora, la expresión evaluará a,
s = 1 + 2 + 2;
Observe que i
a la izquierda de la asignación era 1
, pero a la derecha de la asignación (y en la asignación) se evaluó a 2
, porque la evaluación es de izquierda a derecha, cuando se trata de la segunda y tercera parte de la expresión, El valor de s era 2
.
Permite dividir y computar.
El paréntesis más interno se ejecuta primero y después de que se resuelve todo el paréntesis, luego la expresión se ejecuta de izquierda a derecha.
x ^= (y ^= (x ^= y)); // initial statement
x = x^(y = y^ (x = x^y)); //equals to
() have the highest precedence
x = x^(y = y^ (x = 3^4)); // first highest precedence ()
x = x^(y = y ^ (x = 7)); // still the first x is 3
x = 4 ^(y = 3 ^ (x = 7)); // now 3 ^ 7 =4
x = 4 ^ 4; // now 3 ^ 7 =4
x= 0;