En Java, entiendo que la asignación evalúa el valor del operando correcto, por lo que declaraciones como x == (y = x)evaluar atrue .
Este código, sin embargo, genera false.
public static void main(String[]args){
String x = "hello";
String y = "goodbye";
System.out.println(x.equals(x = y));
}
¿Por qué es esto? Según tengo entendido, primero evalúa (x = y), que asigna xel valor de yy luego devuelve el valor de y. Luego x.equals(y)se evalúa, que debería ser truedesde xy ydebería compartir las mismas referencias ahora, pero en cambio, obtengo false.
¿Que está sucediendo aquí?


x.equals( y = x )xyy?x = yse ejecuta en el lado derecho antes de laxse evalúa en el lado de la mano izquierda?x == (y = x)evalúa como verdadero. El comportamiento de lo que sugieres entonces sería obvio ...Respuestas:
En primer lugar: esa es una pregunta interesante, pero nunca debería aparecer en "código real", ya que asignar a la variable que llamas en la misma línea es confuso incluso si sabes cómo funciona.
Lo que sucede aquí son estos 3 pasos:
x, esto dará como resultado una referencia a la cadena "hola")x = y, evaluar , que cambiaráxpara apuntar a la Cadena "adiós" y también devolverá una referencia a esa Cadena)equalsen el resultado de # 1 usando el resultado de # 2 como parámetro (que serán referencias a las cadenas "hola" y "adiós" respectivamente).Al observar el código de bytes producido para ese método, queda claro (suponiendo que domine 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: returnLa línea # 9 es el paso 1 anterior (es decir, evalúa
xy recuerda el valor).La línea # 10-12 es el paso 2. La carga
y, la duplica (una vez para asignar, una vez para el valor de retorno de la expresión de asignación) y la asigna ax.La línea # 13 invoca
equalsel resultado calculado en la línea # 9 y el resultado de las líneas # 10-12.fuente
x.equals(x = y)=>"hello".equals(x = y)=>"hello".equals(x = "goodbye")=>"hello".equals("goodbye")=>false..tiene mayor precedencia que=.¡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:
Entonces, en:
String x = "hello"; String y = "goodbye"; System.out.println(x.equals(x = y));la ocurrencia de
xbefore.equalsse evalúa primero, antes de la expresión de argumentox = y.Por lo tanto, una referencia a la cadena
hellose recuerda como la referencia de destino antes de que la variable localxse cambie para hacer referencia a la cadenagoodbye. Como resultado, elequalsmétodo se invoca para el objeto de destinohellocon argumentogoodbye, por lo que el resultado de la invocación esfalse.fuente
Es importante recordar que
Stringen java es un objeto y, por lo tanto, una referencia. Cuando usted llamaEstá comprobando si el valor en la ubicación a la que se hace referencia actualmente
xes igual a lo que está pasando. En el interior, está cambiando el valor quexhace referencia , pero todavía está llamandoequalscon la referencia original (la referencia a "hola"). Entonces, ahora mismo su código se está comparando para ver si "hola" es igual a "adiós", lo cual claramente no es así. Después de este punto, si lo usaxnuevamente, resultará en una referencia al mismo valor que y.fuente
"hello".equals((x = y))debería volvertrue?x=yentre paréntesis significa que la expresión(x=y)es ahoragoodbye, mientras que la x exteriorx.equalstiene el valorhellofuente
Reimus dio la respuesta correcta, pero me gustaría dar más detalles.
En Java (y la mayoría de los lenguajes) la convención es variable va a la izquierda, asignación a la derecha.
Vamos a analizarlo:
String x = "hello"; //x <- "hello" String y = "goodbye"; //y <- "goodbye";Para fines de depuración y 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 statementAquí,
x.equals(...)se llama a la referencia original ax, 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 bien, esto 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 debes esforzarte.
fuente
System.out.println("Bytes: "+1024*k);se escribiera como tres declaraciones?He intentado su pregunta en eclipse, ambas expresiones son correctas. 1) x == (y = x) evaluar como verdadero, es cierto porque el valor de x se asigna a y, que es 'hola', luego xey comparan serán iguales, por lo que el resultado será verdadero
2) x.equal (x = y) es falso porque el valor de y se asigna a x que es adiós, entonces xyx comparan su valor será diferente, por lo que el resultado será falso
fuente
Veo la pregunta en términos simples como
"hello".equals("goodbye"). Entonces devuelve falso.fuente
En Java String es una clase.
String x = "hello"; String y = "goodbye";es una cadena de dos diferentes que se refieren a dos valores diferentes que no son iguales y si compara
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 falsefuente
System.out.println(x.equals(x = y));devuelve falso, al contrario de lo que afirma su respuesta.Está viendo si x.equals (asignar xay, devuelve verdadero siempre) así que básicamente x.equals (verdadero)
fuente