Si == compara referencias en Java, ¿por qué se evalúa como verdadero con estas cadenas?

Como se indica, el operador == compara referencias de objetos para verificar si se están refiriendo al mismo objeto en un montón. Si es así, ¿por qué obtengo el “Igual” para este fragmento de código?

public class Salmon { public static void main(String[] args) { String str1 = "Str1"; String str2 = "Str1"; if (str1 == str2) { System.out.println("Equal"); } else { System.out.println("Not equal"); } } } 

El progtwig imprimirá Equal . (Al menos, usa el Sun Hotspot y suns Javac.) Aquí se muestra en http://ideone.com/8UrRrk

Esto se debe al hecho de que las constantes literales de cadena se almacenan en un grupo de cadenas y las referencias de cadenas pueden reutilizarse.

Otras lecturas:

  • ¿Qué es String literal pool?
  • Interno de cadenas

Esto sin embargo:

 public class Salmon { public static void main(String[] args) { String str1 = "Str1"; String str2 = new String("Str1"); if (str1 == str2) { System.out.println("Equal"); } else { System.out.println("Not equal"); } } } 

Se imprimirá Not equal ya que se garantiza que lo nuevo introducirá una nueva referencia.

Entonces, regla general: siempre compare cadenas usando el método equals .

Java almacena todas las cadenas en una tabla de cadenas internamente durante una ejecución. Las referencias a las dos cadenas son idénticas porque en la memoria se almacenan en el mismo lugar. Por lo tanto, Equal .

Su afirmación es correcta, eso == compara referencias de objetos. Prueba lo mismo con cualquier otra clase que no sea Cadenas y no obtendrás el mismo resultado.

Este código no se imprimirá Equal .
Pero si las dos cuerdas fueran iguales, este caso sería especial.

Ahora que ha actualizado su código, es el caso:

Una explicación simple (pero no totalmente exacta) es que el comstackdor ve que las dos cadenas son iguales y hace algo como:

 String str1 = "Str1"; String str2 = str1; 

Lo que realmente sucede aquí es que el comstackdor verá la cadena literal y la colocará en el “conjunto literal String”.

Como una cadena no se puede modificar (es inmutable), los valores literales de las cadenas (los que se encuentran durante la comstackción) se ponen en un “grupo”.
De esta manera, si dos cadenas literales diferentes que tienen el mismo contenido (como en este caso particular), la memoria no se desperdicia para almacenar “Str1” y “Str1” dos veces.

Gente, se está olvidando que el proceso de colocar cadenas literales en el conjunto se llama “internamiento”. La clase String tiene un método llamado interno (). Este método coloca cualquier cadena en el grupo, incluso si no está en el grupo inicialmente (no es literal). Esto significa que código como este:

 String a = "hello"; String b = new String("hello"); b = b.intern(); System.out.println(a == b); 

imprimirá ” true “. Ahora, ¿por qué alguien necesitaría esto? Como se puede imaginar, la comparación de cadenas a.equals(b) puede llevar mucho tiempo si las cadenas tienen la misma longitud pero son diferentes cerca del final. (Solo mira el código fuente de .equals ()).

Sin embargo, comparar referencias directamente es lo mismo que comparar números enteros (punteros en C hablar), que es casi instantáneo.

Entonces, ¿qué te da esto? Velocidad. Si tiene que comparar las mismas cadenas muchas, muchas veces, el rendimiento de su progtwig se beneficiará enormemente si interrumpe estas cadenas . Sin embargo, si va a comparar cadenas solo una vez, no habrá ganancia de rendimiento ya que el proceso de internación en sí mismo usa iguales ().

Espero que esto explique esto.

Gracias

Los comentarios anteriores lo han resumido bastante bien.

No tengo un entorno Java a mano, pero intentar lo siguiente debería aclarar las cosas para ti (espero que esto funcione como lo anticipo).

 String str1 = "Str1"; String str2 = "Str"; str2 += "1"; 

Ahora debería imprimir No igual