2012-03-14 6 views
52

Tengo las siguientes líneas de códigos para comparar cadenas. str1 no es igual a str2, lo que es comprensible ya que compara la referencia del objeto. Pero entonces ¿por qué s1 es igual a s2?¿Qué hace que la comparación de referencia (==) funcione para algunas cadenas en Java?

String s1 = "abc"; 
String s2 = "abc"; 

String str1 = new String("abc"); 
String str2 = new String("abc"); 

if (s1==s2) 
    System.out.println("s1==s2");   
else 
    System.out.println("s1!=s2"); 

if (str1==str2) 
    System.out.println("str1==str2");   
else 
    System.out.println("str1!=str2"); 

if (s1==str1) 
    System.out.println("str1==s1");   
else 
    System.out.println("str1!=s1"); 

Salida:

s1==s2 
    str1!=str2 
    str1!=s1 
+12

¿Has intentado buscar SO primero? :( –

+13

http://stackoverflow.com/questions/7144059/java-string-pool-object-creation, http://stackoverflow.com/questions/4033625/if-compares-references-in-java-why-does -it-evaluate-to-true-with-these-strin, http://stackoverflow.com/questions/6377058/string-reference, http://stackoverflow.com/questions/1903094/java-strings-and-stringpool –

+1

(No estoy cerrando esto, porque no he encontrado otra pregunta * tan enfocada * como esta, pero estoy seguro de que existe) –

Respuesta

80

La cadena del grupo de constantes será esencialmente almacenar en caché todos los literales de cadena por lo que son el mismo objeto debajo, por lo que se ve la salida de lo que hacen por s1==s2. Básicamente, se trata de una optimización en la máquina virtual para evitar la creación de un nuevo objeto de cadena cada vez que se declara un literal, ¡lo que puede ser muy costoso muy rápidamente! Con su ejemplo str1==str2, le está diciendo explícitamente a la máquina virtual que cree nuevos objetos de cadena, por lo que es falso.

Como nota aparte, llamar al método intern() en cualquier cadena lo agregará al grupo constante (y devolverá la cadena que se agrega al grupo). No obstante, no es necesariamente una buena idea hacer esto a menos que esté seguro se trata de cadenas que definitivamente se usarán como constantes, de lo contrario, puede terminar creando pérdidas de memoria difíciles de rastrear.

+2

Me ganaste solo 2 segundos dando la idea del método interno() –

+6

Dormiste perdiendo. jaja j/k. = P –

+1

+1 pero también vale la pena señalar que agregar muchas Cadenas al conjunto constante en general es una mala idea ya que puede causar filtraciones de memoria difíciles de detectar. Solo haga esto para un pequeño número fijo de cadenas que realmente se usarán como constantes (por ejemplo, claves HashMap), nunca para datos de cadena arbitrarios. – mikera

18

s1 y s2 son literales de cadena. Cuando crea un nuevo literal String, el compilador primero verifica si hay literal que lo represente en el grupo de cadenas o no. Si hay un presente, el compilador devuelve ese literal, de lo contrario, el compilador crea uno nuevo.

Cuando creó la Cadena s2, el compilador devuelve la Cadena s1 del grupo como ya se había creado anteriormente. Esa es la razón por la cual s1 y s2 son iguales. Este comportamiento se llama interning.

+0

Estoy un poco confundido cuando dices que "el compilador crea uno nuevo". AFAIK, el compilador está diseñado para crear el código máquina intermedio y no se ejecuta realmente (por lo tanto crea) ningún objeto en la memoria. ¿Quiso decir que el compilador _replaza_ los literales de cadena? Por favor aclara esto. – peakit

+0

No tengo ninguna documentación de respaldo en este momento, pero creo que @Chandra Sekhar se refería al compilador JIT o Just In Time y no al compilador javac. – Robert

3

En Java, las mismas cadenas constantes serán reutilizadas. De modo que s1 y s2 apuntan al mismo objeto "abc" y s1==s2. Pero cuando usa new String("abc"), se creará otro objeto. De modo que s1 != str1.

5

Esto se debe a que los literales de cadena están internados. En esta materia, Java documentations dice:

Todas las cadenas literales y de cadena de valor expresiones constantes son internados

y esto explica por qué s1 y s2 son los mismos (estas dos variables apuntar al mismo internado cadena)

9

Este fenómeno se debe a String interning.

Básicamente, todos los literales de cadena se "almacenan en caché" y se vuelven a usar.

0

Como string es inmutable en java, todo el string literals en caché para la reutilización.

Cuando crea el objeto String utilizando el operador new(), siempre crea un nuevo objeto en la memoria del montón. Por otro lado, si crea un objeto usando la sintaxis literal String, p."Java", puede devolver un objeto existente desde String pool (un caché de objeto String en el espacio generador de Perm, que ahora se mueve al espacio de almacenamiento en la versión reciente de Java), si ya existe. De lo contrario, creará un nuevo objeto de cadena y lo colocará en el grupo de cadenas para su futura reutilización.

String s1 = new String("java"); 
String s2 = new String("java"); 
String s3 = "java"; 
String s4 = "java"; 

enter image description here

Please refer this link

Cuestiones relacionadas