java string-concatenation string-interning

Java cadena de concatenación e internamiento



string-concatenation string-interning (3)

De documentos internos ()

Todas las cadenas literales y expresiones constantes con valores de cadena están internados. Los literales de cadena se definen en la sección 3.10.5 de la Especificación del lenguaje Java ™.

Y de JLS 3.10.5

  • Las cadenas calculadas por expresiones constantes (§15.28) se calculan en tiempo de compilación y luego se tratan como si fueran literales.
    • Las cadenas calculadas por concatenación en tiempo de ejecución se crean recientemente y, por lo tanto, son distintas.

Su cadena b1 no está realmente internada. De ahí la diferencia.

Pregunta 1

String a1 = "I Love" + " Java"; String a2 = "I Love " + "Java"; System.out.println( a1 == a2 ); // true String b1 = "I Love"; b1 += " Java"; String b2 = "I Love "; b2 += "Java"; System.out.println( b1 == b2 ); // false

En el primer caso, entiendo que es una concatenación de dos literales de cadena, por lo que el resultado "Amo Java" se internará, dando el resultado verdadero. Sin embargo, no estoy seguro sobre el segundo caso.

Pregunta 2

String a1 = "I Love" + " Java"; // line 1 String a2 = "I Love " + "Java"; // line 2 String b1 = "I Love"; b1 += " Java"; String b2 = "I Love "; b2 += "Java"; String b3 = b1.intern(); System.out.println( b1 == b3 ); // false

Lo anterior devuelve falso, pero si comento las líneas 1 y 2, devuelve verdadero. ¿Porqué es eso?


La primera parte de su pregunta es simple: el compilador de Java trata la concatenación de múltiples literales de cadena como un solo literal de cadena, es decir

"I Love" + " Java"

y

"I Love Java"

son dos literales de cadena idénticos, que se internan correctamente.

El mismo comportamiento interno no se aplica a la operación += en cadenas, por lo que b1 y b2 se construyen realmente en tiempo de ejecución.

La segunda parte es más complicada. Recuerde que b1.intern() puede devolver b1 o algún otro objeto String que sea igual a él. Cuando mantiene a1 y a2 , recupera a1 de la llamada a b1.intern() . Cuando b1.intern() a1 y a2 , no hay una copia existente para devolver, por lo que b1.intern() te devuelve b1 .


Respuesta a la pregunta 1:

No puede comparar dos cadenas con == . El == compara dos tipos de datos primitivos (int, long, float, double y boolean) o referencias de objeto. Lo que significa que si las varibales de referencia (a1, a2, b1, b2) no tienen la misma referencia (lo que significa que no apuntan al mismo objeto en la memoria), no son iguales (comparación con == ).

Si compararas con b1.equals(b2) , la expresión sería verdadera ya que los datos del objeto son los mismos.

En el primer caso, Java es lo suficientemente inteligente como para concatenar las cadenas antes de asignarles algo de memoria (incluso antes de la compilación), lo que significa que ambas cadenas se almacenan en la misma dirección. Por lo tanto, las variables a1 y a2 hacen referencia al mismo objeto y son iguales ( == ).

En el segundo caso, primero asigna a las variables un valor diferente (a diferencia del primer caso). Esto significa que obtienen una dirección separada en la memoria. Incluso si cambia el valor para que sean iguales, la dirección no cambia y una comparación con == evalúa como falsa. Esto sucede durante el tiempo de ejecución.

En cuanto a la pregunta 2: @dasblinkenlight ya dio una buena respuesta a eso.