¿Se almacenarán dos cadenas con el mismo contenido en la misma ubicación de memoria?

Esta es una pregunta que recibí en una entrevista.

Tengo dos cadenas definidas como

String s1="Java"; String s2="Java"; 

Mi pregunta es si estas dos referencias apuntan a la misma ubicación de memoria. En general, cuando creamos cadenas idénticas (sin palabra clave nueva), ¿el contenido se almacena en la memoria solo una vez y todos los objetos String con el mismo contenido solo hacen referencia a la misma ubicación, sin almacenar la cadena “Java” de forma redundante? Los códigos hash de s1 y s2 son iguales. Pero, ¿los hashcodes dependen directamente de la ubicación de la memoria del objeto?

El proceso de combinación de cadenas idénticas se denomina ” internamiento ” y se ha realizado durante muchos años por muchos comstackdores de lenguaje, pero no siempre. La respuesta a la pregunta, especialmente la expandida por @ GennadyVanin – Novosibirsk, depende del idioma y la implementación del comstackdor. Para Java, todas las cadenas constantes se internan, según lo requerido por la Especificación del lenguaje Java . Pero eso solo son expresiones de cadena constantes, y solo cuando se comstackn al mismo tiempo. Si tiene dos cadenas de Java suficientemente separadas en tiempo y espacio ( por ejemplo , comstackdas en archivos JAR separados), no serán el mismo objeto. De manera similar, las cadenas de Java creadas dinámicamente ( p . Ej. , La salida de varios métodos toString() ) no serán intercaladas a menos que el método lo solicite específicamente a través de String.intern() . Y sí, todos los usos de una cadena interna compartirán las mismas ubicaciones de memoria: esa es una gran parte de por qué las cadenas se internan en primer lugar.

En cuanto a otros idiomas, esa es una pregunta más importante, pero con toda la información en estas respuestas, estoy seguro de que puedes investigarla en la web. Baste decir que no hay un acuerdo universal sobre cómo esto se debe hacer.

Cuando el comstackdor optimiza los literales de cadena, ve que s1 y s2 tienen el mismo valor y, por lo tanto, solo necesita un objeto de cadena . Es seguro porque String es inmutable en Java.

 String s1="Java"; String s2="Java"; System.out.println(s1== s2); 

Esto da resultado true porque s1 y s2 apuntan al mismo objeto.

String Pool es el mecanismo que todas las cadenas ya definidas se almacenan en algún ‘grupo’ y antes de crear un nuevo comstackdor de objetos String comprueba si dicha cadena ya está definida.

 String s1="Java"; String s2="Java"; My question is whether these two references point to the same memory location 

Dumb citando §3.10.5 de la especificación del lenguaje Java :

Un literal de cadena es una referencia a una instancia de clase String ( §4.3.1 , §4.3.3 ).

Además, un literal de cadena siempre se refiere a la misma instancia de clase String. Esto se debe a que los literales de cadena (o, más generalmente, las cadenas que son los valores de las expresiones constantes ( §15.28 )) son “internados” para compartir instancias únicas, utilizando el método String.intern.

Y lea los comentarios para codificar el ejemplo allí:

Este ejemplo ilustra seis puntos:

  • Las cadenas literales dentro de la misma clase (§8) en el mismo paquete (§7) representan referencias al mismo objeto String (§4.3.1).

  • Las cadenas literales dentro de diferentes clases en el mismo paquete representan referencias al mismo objeto String.

  • Las cadenas literales dentro de diferentes clases en diferentes paquetes también representan referencias al mismo objeto String.

  • Las cadenas calculadas por expresiones constantes (§15.28) se calculan en tiempo de comstackción y luego se tratan como si fueran literales.

  • Las cadenas calculadas por concatenación en el tiempo de ejecución son de nueva creación y, por lo tanto, distintas.

  • El resultado de internar explícitamente una cadena calculada es la misma cadena que cualquier cadena literal preexistente con los mismos contenidos.

Ejemplo.

Primer ejemplo

 String s1 = "FirstString"; String s2 = "FirstString"; if(s1 == s2) { //This condition matched true because java don't make separate object for these two string. Both strings point to same reference. } 

Segundo ejemplo

 String s1= "FirstString"; String s2 = new String("FirstString"); if(s1.equals(s2)) { //This condition true because same content. } if(s1 == s2) { //This condition will be false because in this java allocate separate reference for both of them } 

Conclusión: Java comprueba si la cadena existe o no. Si creamos el objeto de la segunda cadena usando new y tenemos un contenido diferente, entonces crea un objeto y asigna una referencia diferente. En caso de que no creemos el objeto usando new y tengamos el mismo contenido, entonces asigna la misma referencia que contiene la primera cadena. .

Agregar a otros: nueva palabra clave siempre obliga a crear un nuevo objeto. Si declaras como a continuación:

 String s1 = "some"; String s2 = "some"; 

Luego, utilizando el mecanismo de agrupación de cadenas, las referencias s1 y s2 se referirán al mismo objeto String con el valor “some”.

Cuando tengas

 String str1 = new String("BlaBla"); //In the heap! String str2 = new String("BlaBla"); //In the heap! 

luego está creando explícitamente un objeto String través de un new operador (y constructor). En este caso, tendrá cada objeto apuntando a una ubicación de almacenamiento diferente .

Pero si tienes:

 String str1 = "BlaBla"; String str2 = "BlaBla"; 

entonces tienes una construcción implícita. ¡Dos literales de cadenas comparten el mismo almacenamiento si tienen los mismos valores, esto es porque Java conserva el almacenamiento de las mismas cadenas! (Cuerdas que tienen el mismo valor)

 String s1="Java"; String s2="Java"; 

ambos puntos al mismo objeto. para más detalles haga clic aquí

 String s1="Java"; String s2="Java"; 

¿Señalan a la misma ubicación de memoria?

Originalmente dije “no”, pero en el caso anterior, vea la respuesta de StringPool a la que se hace referencia a continuación, en realidad es sí …

“cuando creamos cadenas idénticas (sin nueva palabra clave), el contenido se almacena en la memoria solo una vez y todos los objetos String con el mismo contenido solo hacen referencia a la misma ubicación”

… tipo de ver respuesta detallada en cuestión “Java Strings y StringPool”

“Los códigos hash de s1 y s2 son iguales. ¿Pero los hashcodes dependen directamente de la ubicación de memoria del objeto?”

No, los códigos hash dependen del contenido del String

SÍ, Andrew Hare recibió respuesta al desbordamiento de stack en este enlace https://stackoverflow.com/a/2486195/4835894 .

Básicamente, un grupo interno de cadenas permite que el tiempo de ejecución ahorre memoria al preservar cadenas inmutables en un grupo de modo que las áreas de la aplicación puedan reutilizar instancias de cadenas comunes en lugar de crear múltiples instancias de la misma.