2009-12-07 6 views
10

Me enteré de que es del demonio para probar la igualdad de Cadenas con == en lugar de String.equals(), porque cada Cadena era una referencia a su propio objeto.Java: ¿Por qué se puede probar la igualdad de cadenas con ==?

Pero si uso algo así como

System.out.println("Hello" == "Hello"); 

imprime cierto.

¿Por qué?

+1

Eche un vistazo a http://stackoverflow.com/questions/1091045/is-it-good-practice-to-use-java-lang-string-intern. También discuten este tema. – ewernli

+0

Por favor, publique un ejemplo que muestre cómo "esto funciona ahora". –

+0

¡Qué gracioso salió esto! Estaba invirtiendo {string == null? "": cadena} - todas mis pruebas pasaron, pero cuando las cadenas comenzaron a leerse en la base de datos ... – Stephen

Respuesta

26

No es así. Todavía es algo malo de hacer, aún estarás probando la igualdad de referencia en lugar de la igualdad de valores.

public class Test 
{ 
    public static void main(String[] args) 
    { 
     String x = "hello"; 
     String y = new String(x); 
     System.out.println(x == y); // Prints false 
    } 
} 

Si está viendo == la prueba de "trabajo" ahora es porque realmente tiene las mismas referencias. La razón más común para ver esto probablemente se deba a la internación de los literales de cadena, pero que ha estado en Java siempre:

public class Test 
{ 
    public static void main(String[] args) 
    { 
     String x = "hello"; 
     String y = "hel" + "lo"; // Concatenated at compile-time 
     System.out.println(x == y); // Prints true 
    } 
} 

Esto está garantizado por section 3.10.5 de la especificación del lenguaje Java:

Cada cadena literal es una referencia (§4.3) a una instancia (§4.3.1, §12.5) de la clase String (§4.3.3). Los objetos de cadena tienen un valor constante. Cadena literales -o, más en general, las cadenas que son los valores de las expresiones constantes (§15.28) -están "internados" así que para compartir instancias únicas, usando el método String.intern.

+0

Gracias, pero ¿por qué funciona si uso dos literales idénticos? – Zeemee

+0

@Mulmoth: Ver la parte inferior de mi respuesta (editada). –

+0

Guau, eso es completamente nuevo para mí, ¡gracias! – Zeemee

3

No ha cambiado. Sin embargo, el compilador de Java usa string.intern() para asegurarse de que las cadenas idénticas en el código fuente se compilan en el mismo objeto String. Sin embargo, si carga una cadena desde un archivo o base de datos, no será el mismo objeto, a menos que lo fuerce usando String.intern() u otro método.

Es una mala idea, y aún se debe utilizar .equals()

+1

Internar manualmente Objetos de cadena es arriesgado porque nunca se pueden internar o recoger basura. Uno podría fácilmente consumir toda la memoria disponible de esa manera. –

+0

@Adriaan - insachable interned Las cadenas son basura recolectada. Esto aparentemente se implementó en JDK 1.2. –

1

Mira, este es un concepto difícil.

Hay una diferencia entre:

// These are String literals 
String a = "Hiabc"; 
String b = "abc"; 
String c = "abc"; 

y

// These are String objects. 
String a = new String("Hiabc"); 
String b = new String("abc"); 
String c = new String("abc"); 

Si sus cuerdas eran objetos, es decir,

String b = new String("abc"); 
String c = new String("abc"); 

Entonces, dos objetos diferentes habrían sido creada en el conjunto de cadenas en dos ubicaciones de memoria diferentes y haciendo

b == c 

habría resultado false.

Pero desde sus String b y String c son literales,

b == c 

resultados true. Esto se debe a que no se crearon dos objetos diferentes. Y tanto a como b apuntan a la misma Cadena en la memoria de la pila.

Esta es la diferencia. Tienes razón, == se compara para la ubicación de la memoria. Y esa es la razón,

a.substring(2, 5) == b; // a,substring(2, 5) = "abc" which is at the location of b, and 
b == c // will be true, coz both b and c are literals. And their values are compared and not memory locations. 

Con el fin de tener dos cadenas separadas con los mismos valores pero en diferentes lugares de la String pool y NOstack memory, es necesario crear objetos String como se muestra arriba.

Así,

a.substring(2, 5) == b; // and 
b == c; // will be false. as not both are objects. Hence are stored on separate memory locations on the String pool. 

que tienen que utilizar

a.substring(2, 5).equals(b); 
b.equals(c); 

en el caso de los objetos.

Cuestiones relacionadas