operacion - Ejecución del operador de asignación Java
operadores de comparacion en java (9)
En Java, entiendo que la asignación se evalúa según el valor del operando correcto, por lo que las afirmaciones como
x == (y = x)
evalúan como
true
.
Este código, sin embargo, da como resultado
false
.
public static void main(String[]args){
String x = "hello";
String y = "goodbye";
System.out.println(x.equals(x = y));
}
¿Por qué es esto?
En mi entendimiento, primero evalúa
(x = y)
, que asigna
x
el valor de
y
, y luego devuelve el valor de
y
.
Luego se
x.equals(y)
, lo que debería ser
true
ya que
x
e
y
deberían compartir las mismas referencias ahora, pero en su lugar, obtengo
false
.
¿Que está sucediendo aquí?
¡Buena pregunta! Y el JLS tiene la respuesta ...
§15.12.4.1 (Ejemplo 15.12.4.1-2). Orden de evaluación durante la invocación del método:
Como parte de la invocación de un método de instancia, hay una expresión que denota el objeto a invocar. Esta expresión parece estar completamente evaluada antes de que se evalúe cualquier parte de cualquier expresión de argumento a la invocación del método.
Entonces, en
String x = "hello";
String y = "goodbye";
System.out.println(x.equals(x = y));
la aparición de
x
antes de
.equals
se evalúa primero, antes de la expresión de argumento
x = y
.
Por lo tanto, una referencia a la cadena
hello
se recuerda como la referencia de destino antes de que la variable local
x
se cambie para referirse a la cadena
goodbye
.
Como resultado, se invoca el método
equals
para el objeto de destino
hello
con argumento
goodbye
, por lo que el resultado de la invocación es
false
.
En java String es una clase.
String x = "hello";
String y = "goodbye";
es una cadena diferente que se refiere a dos valores diferentes que no son iguales y si se comparan
System.out.println(x.equals(x = y));
//this compare value (hello and goodbye) return true
System.out.println(x == (y = x));
// this compare reference of an object (x and y) return false
En primer lugar: esa es una pregunta interesante, pero nunca debe aparecer en "código real", ya que asignar a la variable a la que llama en la misma línea es confuso incluso si sabe cómo funciona.
Lo que pasa aquí son estos 3 pasos:
-
averiguar a qué objeto llamar el método (es decir, evaluar la primera
x
, esto dará como resultado una referencia a la cadena "hola") -
averiguar los parámetros (es decir, evaluar
x = y
, que cambiaráx
para apuntar a la Cadena "adiós" y también devolverá una referencia a esa Cadena) -
llamar al método
equals
al resultado de # 1 usando el resultado de # 2 como parámetro (que será referencias a las cadenas "hello" y "goodbye" respectivamente).
Mirar el código de bytes producido para ese método lo aclara (suponiendo que sea fluido en el código de bytes de Java):
0: ldc #2 // String hello
2: astore_1
3: ldc #3 // String goodbye
5: astore_2
6: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
9: aload_1
10: aload_2
11: dup
12: astore_1
13: invokevirtual #5 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
16: invokevirtual #6 // Method java/io/PrintStream.println:(Z)V
19: return
La línea # 9 es el paso 1 anterior (es decir, evalúa
x
y recuerda el valor).
La línea 10-12 es el paso 2. Carga
y
, lo duplica (una vez para asignar, una vez para el valor de retorno de la expresión de asignación) y lo asigna a
x
.
La línea # 13 invoca
equals
en el resultado calculado en la línea # 9 y el resultado de las líneas # 10-12.
Es importante recordar que una
String
en java es un objeto, y por lo tanto una referencia.
Cuando usted llama
x.equals(...)
Se está comprobando si el valor en la ubicación a la que hace referencia actualmente
x
es igual a lo que está pasando. En el interior, está cambiando el valor al que
x
hace
referencia
, pero sigue llamando a la referencia
original
(la referencia a "hola ").
Entonces, en este momento su código se está comparando para ver si "hola" es igual a "adiós", que claramente no lo es.
Después de este punto, si usa
x
nuevamente, resultará en una referencia al mismo valor que y.
He intentado su pregunta en eclipse sus dos expresiones son correctas. 1) x == (y = x) evalúa que es verdadero porque el valor de x se asigna a y, que es ''hola'', luego que x e y se comparan, serán iguales y el resultado será verdadero
2) x.equal (x = y) es falso porque el valor de y asigna a x que es adiós, entonces x y x comparan su valor será diferente, por lo que el resultado será falso
Reimus dio la respuesta correcta, pero me gustaría explicarlo.
En Java (y en la mayoría de los lenguajes) la convención es variable va a la izquierda, la asignación a la derecha.
Vamos a desglosarlo:
String x = "hello";
//x <- "hello"
String y = "goodbye";
//y <- "goodbye";
Para fines de depuración, así como la legibilidad del código, siempre es una buena práctica dividir las líneas para que solo hagan una cosa.
System.out.println(x.equals(x = y)); //Compound statement
Aquí, se
x.equals(...)
en la referencia original a x, o "hola", se actualiza para la segunda referencia.
Escribiría esto como (y esto le dará la respuesta esperada):
x = y;
// x <- y = "goodbye"
boolean xEqualsX = x.equals(x);
// xEqualsX <- true
System.out.println(xEqualsX);
// "true"
Ahora parece obvio que debería comportarse de esta manera, pero también es muy fácil ver exactamente lo que está sucediendo en cada línea, que es algo por lo que debe esforzarse.
Se ve si x.equals (asignar x a y, devuelve true siempre), así que básicamente x.equals (true)
Veo la pregunta en términos simples como
"hello".equals("goodbye")
.
Así que devuelve falso.
x=y
en el paréntesis significa que la expresión
(x=y)
ahora es
goodbye
, mientras que la x externa en
x.equals
mantiene el valor
hello