java - memories - ps eden space
¿Se almacenarán dos cadenas con el mismo contenido en la misma ubicación de memoria? (9)
Esta es una pregunta que obtuve 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 palabras clave nuevas), ¿el contenido se almacena en la memoria solo una vez y todos los objetos de la cadena con el mismo contenido se refieren a la misma ubicación, sin almacenar la cadena "Java" de forma redundante? Los códigos hash de s1 y s2 son los mismos. Pero, ¿los hashcodes dependen directamente de la ubicación de memoria del objeto?
Agregando a otros: la nueva palabra clave siempre obliga a crear un nuevo objeto. Si usted declara como a continuación:
String s1 = "some";
String s2 = "some";
Luego, utilizando el mecanismo de agrupación de cadenas, ambas referencias s1 y s2 se referirán al mismo objeto de cadena con el valor "algo".
Cuando el compilador optimiza tus literales de cadena, ve que tanto s1 como s2 tienen el mismo valor y, por lo tanto, solo necesitas 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 un resultado true
porque s1
y s2
apuntan al mismo objeto.
String Pool es el mecanismo por el cual todas las cadenas ya definidas se almacenan en algunos "grupos" y, antes de crear una nueva cadena, el compilador de objetos comprueba si dicha cadena ya está definida.
Cuando tengas
String str1 = new String("BlaBla"); //In the heap!
String str2 = new String("BlaBla"); //In the heap!
entonces 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 la construcción implícita. Los literales de dos cadenas comparten el mismo almacenamiento si tienen los mismos valores, ¡esto se debe a que Java conserva el almacenamiento de las mismas cadenas! (Cadenas que tienen el mismo valor)
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 verifica si existe una cadena o no. Si creamos el objeto de la segunda cadena con un contenido nuevo y diferente, entonces creará un objeto y le asignaremos una referencia diferente. En el caso de Si no creamos el objeto utilizando un nuevo y tenemos el mismo contenido, asignará la misma referencia que la primera cadena que contiene .
El proceso de combinación de cadenas idénticas se denomina " interning " y se ha realizado durante muchos años por muchos compiladores de idiomas, pero no siempre. La respuesta a la pregunta, especialmente la ampliada por @ GennadyVanin - Novosibirsk, depende del lenguaje y la implementación del compilador. Para Java, todas las cadenas constantes se internan, como lo requiere la especificación del lenguaje Java . Pero eso es solo expresiones de cadena constantes, y solo cuando se compilan al mismo tiempo. Si tiene dos cadenas Java suficientemente separadas en tiempo y espacio ( por ejemplo , compiladas en archivos JAR separados), no serán el mismo objeto. De manera similar, las cadenas Java creadas dinámicamente ( por ejemplo , la salida de varios métodos toString()
) no se internarán a menos que el método lo solicite específicamente a través de String.intern()
. Y sí, todos los usos de una cadena internada compartirán las mismas ubicaciones de memoria, eso 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 de estas respuestas, estoy seguro de que puede investigarlo en la web. Basta con decir que no existe un acuerdo universal sobre cómo se debe hacer esto.
SÍ, Andrew Hare recibió respuesta en el desbordamiento de pila en este enlace https://.com/a/2486195/4835894 .
Básicamente, un grupo interno de cadenas permite que un tiempo de ejecución ahorre memoria al preservar cadenas inmutables en un grupo para que las áreas de la aplicación puedan reutilizar instancias de cadenas comunes en lugar de crear múltiples instancias.
String s1="Java";
String s2="Java";
Ambos puntos apuntan al mismo objeto. para más detalles haga clic aquí
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 la clase String ( §4.3.1 , §4.3.3 ).
Además, un literal de cadena siempre se refiere a la misma instancia de la clase String. Esto se debe a que los literales de cadena (o, más generalmente, las cadenas que son valores de expresiones constantes ( §15.28 ) - se "internan" 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 compilación y luego se tratan como si fueran literales.
Las cadenas calculadas por concatenación en tiempo de ejecución se crean de nuevo y, por lo tanto, son distintas.
El resultado de internar explícitamente una cadena computada es la misma cadena que cualquier cadena literal preexistente con el mismo contenido.
String s1="Java";
String s2="Java";
¿Apuntan 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 sí.
"cuando creamos cadenas idénticas (sin una nueva palabra clave), el contenido se almacena en la memoria solo una vez y todos los objetos de la cadena con el mismo contenido se refieren a la misma ubicación"
... tipo de ver respuesta detallada en la pregunta "Java Strings y StringPool"
"Los códigos hash de s1 y s2 son los mismos. ¿Pero los códigos hash dependen directamente de la ubicación de la memoria del objeto?"
No los hashcodes dependen del contenido de la cadena.