Pregunta

Si tiene dos instancias de una cadena, y son iguales, en Java van a compartir la misma memoria. ¿Cómo es esto implementado bajo el capó?

EDIT: Mi aplicación utiliza un gran número de objetos String, muchos de los cuales son idénticos. ¿Cuál es la mejor manera de hacer uso de la piscina constante String de Java, que se evite la creación de la aplicación personalizada de peso mosca?

¿Fue útil?

Solución

mirar el código fuente de java.lang.String (la fuente para toda api java es parte de la JDK).

Para resumir: Una cadena que envuelve una subsecuencia de un char[]. Eso char[] respaldo no se modifica. Esto se logra ni fugas ni la captura de este char[] fuera de la clase String. Sin embargo, varios Strings pueden compartir la misma char[] (ver Aplicación de String.substring).

También existe el mecanismo de la internación, como se explica en las otras respuestas.

Otros consejos

Si tiene dos instancias de una cadena, y son iguales, en Java que compartirán la misma memoria

Esto es realmente no es 100% cierto.

Esta entrada de blog es una explicación decente de por qué esto es así, y lo que el cadena de memoria constante es.

Los literales de cadena se internó en Java, por lo que no hay realmente sólo un objeto String con múltiples referencias (cuando son iguales, lo que no siempre es el caso). Véase el artículo java.net Todo sobre pasante () para más detalles.

También hay un buen ejemplo / explicación en la sección 3.10.5 literales de cadena de los JLS que cuando se habla de cadenas son internados y cuándo van a ser distintos.

Eso no es necesario cierto. Ejemplo:

String s1 = "hello";
String s2 = "hello";
System.out.println(s1 == s2); // true

pero:

String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1 == s2); // false

Ahora la segunda forma se recomienda. Algunos (incluido yo) pensar que String ni siquiera debe tener un constructor público. Una versión mejorada de lo anterior sería:

String s1 = new String("hello").intern();
String s2 = new String("hello").intern();
System.out.println(s1 == s2); // true

Es evidente que no es necesario hacer esto para un String constante. Es ilustrativo.

Lo importante de esto es que si usted está aprobó una String o conseguir uno de una función que no se puede confiar en la String siendo canónica . Un canónica satisface Object esta igualdad:

a.equals(b) == b.equals(a) == (a == b)

para instancias no null a, b, de un Class dado.

Para responder a su pregunta editada, Sun JVM tiene una opción -XX:+StringCache, que en mi observación puede reducir el consumo de memoria de una aplicación pesada Cadena de manera significativa.

De lo contrario, se tiene la posibilidad de internar a sus cadenas, pero me gustaría tener cuidado con eso. Cadenas que son muy grandes y ya no hace referencia todavía usan la memoria de la vida de la JVM.

Editar (en respuesta a los comentarios): La primera vez que descubrí sobre la opción de StringCache aquí :

-XX:. + StringCache Permite el almacenamiento en caché de cadenas comúnmente asignados

Tom Hawtin describe algún tipo de almacenamiento en caché para mejorar algunos puntos de referencia. Mi observación cuando lo puse sobre la idea era que la huella de la memoria (después de una recolección completa) fue mucho más abajo que no lo tienen. No es un parámetro documentado, y puede de hecho ser sólo acerca de la optimización de algunos puntos de referencia. Mi observación es que ayudó, pero yo no construiría un importante sistema basado en él.

Dos cosas a tener cuidado con:

  1. No utilice el constructor new String("abc"), sólo tiene que utilizar el "abc" literal.
  2. Aprender a usar pasante ( ) método en la clase de cadena. Especialmente cuando concatenación de cadenas juntos o cuando la conversión de matriz de caracteres / matriz de bytes / etc en una cadena.

intern() Siempre devuelve cadenas que se agrupan.

Si sus cadenas idénticas provienen de un conjunto fijo de valores posibles, a continuación, un tipo seguro enumeración es lo que queremos aquí. No sólo va a reducir el número de cuerdas, sino que hará que para una aplicación más sólida. Toda su aplicación va a conocer esta cadena tiene una semántica que se le atribuye, tal vez incluso algunos métodos de conveniencia.

Mis optimizaciones favoritos son siempre las que se pueden defender como hacer que el código mejor , no sólo más rápido. Y 9 de cada 10 veces, la sustitución de una cadena con un tipo concreto conduce a un código más correcta y autodocumentado.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top