programas tienden a contener una gran cantidad de literales de cadena en su código. En Java, estas constantes se recopilan en algo llamado tabla de cadenas para mayor eficiencia. Por ejemplo, si se utiliza la cadena "Name: "
en diez lugares diferentes, la JVM (por lo general) tiene sólo una instancia de esa cadena y en los diez lugares donde se consume, las referencias apuntan a que una instancia. Esto ahorra memoria.
Esta optimización es posible porque String
es inmutable. Si fuera posible cambiar una Cadena, cambiarla un lugar significaría que también cambia en las otras nueve. Es por eso que cualquier operación que cambie una cadena devuelve una nueva instancia. Es por eso que si usted hace esto:
String s = "boink";
s.toUpperCase();
System.out.println(s);
imprime boink
, no BOINK
.
Ahora hay una más poco complicado: varias instancias de java.lang.String
puede apuntan a la misma subyacente char[]
por sus datos de caracteres, en otras palabras, pueden ser diferentes vistas en el mismo char[]
, utilizando sólo una rebanada de la matriz. De nuevo, una optimización para la eficiencia. El método substring()
es uno de los casos donde esto sucede.
s1 = "Fred47";
//String s1: data=[ 'F', 'r', 'e', 'd', '4', '7'], offset=0, length=6
// ^........................^
s2 = s1.substring(2, 5);
//String s2: data=[ 'F', 'r', 'e', 'd', '4', '7'], offset=2, length=3
// ^.........^
// the two strings are sharing the same char[]!
En su pregunta SCJP, todo esto se reduce a:
- La cadena
"Fred"
se toma de la tabla de cadenas.
"47"
La cadena se toma de la tabla de cadenas.
"Fred47"
La cadena se crea durante la llamada al método.// 1
- La cadena
"ed4"
se crea durante la llamada al método, compartir la misma matriz de soporte como "Fred47"
// 2
- La cadena
"ED4"
se crea durante la llamada al método. // 3
- El
s.toString()
no crea una nueva, simplemente devuelve this
.
Un caso extremo interesante de todo esto: considerar lo que sucede si usted tiene un largo de cuerda, por ejemplo, una página web tomada de Internet, digamos que la longitud de la char[]
es de dos megabytes. Si se toma el substring(0, 4)
de esto, se obtiene una nueva cadena que se ve como si fuera sólo cuatro caracteres de longitud, pero todavía comparte esos dos megabytes de datos de respaldo. Esto no es tan común en el mundo real, ¡pero puede ser una gran pérdida de memoria! En el (raro) caso en que se encuentre con este problema, puede usar new String(hugeString.substring(0, 4))
para crear una Cadena con una nueva matriz de respaldo pequeña.
Por último, es posible forzar una cadena en la tabla de cadenas en tiempo de ejecución llamando intern()
en él. La regla básica en este caso: no lo hagas. La regla extendida: no lo haga a menos que haya utilizado un generador de perfiles de memoria para asegurarse de que sea una optimización útil.
Me imagino que el compilador inline los dos primeros estados y eliminar el último (redundante) Método de llamada. Eso te deja con "Fred47", "ed4", "ED4". –
@Jared 's' no es una * expresión constante en tiempo de compilación *, así que eso no sucede. (Compile el código y use 'javap -c', o incluso' cadenas'). –
posible duplicado de [Java - ¿Cuántos String Objects?] (Http://stackoverflow.com/questions/17898236/java-how-many -string-objects) –