2011-06-15 10 views
7

estaba trabajando en el programa básico de Java y encontré algo realmente divertido que estoy compartiendo contigo. foo() da salida (s == s1) = falso y la barra da (s == s1) = verdadero.¿Por qué obtengo resultados diferentes al comparar cadenas después de usar una concatenación diferente en Java?

Quiero saber por qué sucede esto.

public class StringTest 
{ 
    public static void main(String[] args){ 
    foo(); 
    bar(); 
    } 
    public static void foo(){ 
    String s = "str4"; 
    String s1 = "str" + s.length(); 
    System.out.println("(s==s1) = " + (s1==s)); 
    } 
    public static void bar(){ 
    String s = "str4"; 
    String s1 = "str" + "4"; 
    System.out.println("(s==s1) = " + (s1==s)); 
} 
} 
+1

Si está tratando de comparar valores de cadena, debería estar haciendo ['equals'] (http: // downlo ad.oracle.com/javase/6/docs/api/java/lang/String.html#equals(java.lang.Object)) – asgs

+0

Nota: las etiquetas HTML no funcionan aquí para formatear el código. – Jesper

+0

Me pregunto cómo los errores humanos se relacionan con este problema ...;) – Nix

Respuesta

16

En este último caso, el compilador optimiza la concatenación de cadenas. Como esto se puede hacer en tiempo de compilación, ambos hacen referencia al mismo objeto de cadena constante.

En el primer caso, la llamada length() no se puede optimizar durante el tiempo de compilación. En tiempo de ejecución, se crea un nuevo objeto de cadena, que no es idéntico a la constante de cadena (pero igual)

+0

+1 para explicar * por qué * es así – Sorrow

+0

Gracias amigo ... !! – Chakravyooh

+0

, pero ¿qué pasa si voy a cambiar el valor de s1 en la barra() después de ompersion .. ?? – Chakravyooh

3

La concatenación de cadena en bar() se puede hacer en tiempo de compilación, porque es una expresión compuesta por más que el tiempo de compilación constantes. Aunque la longitud de la Cadena s es obviamente conocida en tiempo de compilación, el compilador no sabe que length() devuelve ese valor conocido, por lo que no se utilizará como una constante.

+0

+1, pero nadie ha mencionado el uso de '.equals()' para comparar la igualdad de cadenas? – Mikaveli

+1

@Mikaveli: Creo que @Chakravyooh lo sabe, pero es irrelevante para la pregunta. Si usa 'igual()', entonces el comportamiento interesante aquí simplemente está oculto, y ¿dónde está la diversión en eso? –

0

Probablemente tiene que ver con el hecho de que foo() probablemente esté creando una nueva instancia de String en s. length() (. toString()), donde como bar() es simplemente concatenar una constante. No sé el quid de la cuestión de la misma, pero mi instinto me dice que en esa dirección

2

Cuando se escribe una línea de código como este:

String s1 = "str" + "4"; 

entonces el compilador es suficientemente inteligente para optimizar este a:

String s1 = "str4"; 

Las cadenas literales en Java se administran en un grupo de cadenas. Cuando tiene dos cadenas literales que tienen el mismo contenido (como s y s1 en su segundo ejemplo), se creará un solo objeto String que las dos variables compartirán.

El operador == en Java comprueba si dos variables hacen referencia al mismo objeto. Dado que solo hay un objeto String en el segundo ejemplo, s == s1 será true.

0

Si tuviera que adivinar, diría que el compilador de java realiza algunas optimizaciones en la barra(). En tiempo de compilación, está claro que "str" ​​+ "4" puede reemplazarse por "str4", que (dado que las cadenas son objetos inmutables) es el mismo objeto que "str4". La cadena utilizada para la inicialización s.

Dentro de foo() la optimización no es tan sofisticada. En general, el valor s1-variable no se puede predecir con mucha facilidad (de hecho, este ejemplo es bastante sofisticado). Entonces el compilador de Java producirá dos variables diferentes para s y s1.

¡El operador "==" no compara el valor de las cadenas! Comprueba si estos son los mismos Objetos. Para comparar los valores de las cadenas utilizan los "iguales" método como este:

String s = "str4"; 
String s1 = "str" + s.length(); 
System.out.println("(s==s1) = " + (s1.equals(s2)); 
0

usted debe tratar de jugar con el método interno de la clase String. Java mantiene algo así como el diccionario donde se almacenan todas las cadenas diferentes. Cuando crea un objeto de cadena que se puede evaluar en tiempo de compilación, Java lo busca en su diccionario.Si funde la cadena, almacena solo una referencia a esta cadena (que en realidad es devuelta por el método interno).

Usted debe notar que: "str4" == ("str" + "str4".length()) vuelve falsa, pero "str4" == ("str" + "str4".length()).intern() vuelve verdadera, porque el único "contenedor" es un objeto diferente.

2
  • String s1 = "str" + s.length();
  • String s1 = "str" + "4";

En primer caso s.length() devolverá un valor de tipo int , En segundo caso el tipo es cadena A pesar de que el número es 4 en ambos casos, pero los tipos no son los mismos :)

Cuestiones relacionadas