Si hay una característica revolucionaria que ha hecho que Java fuera diferente y disruptivo desde el inicio son los Java String con su icónica inmutabilidad desde su diseño y esto no fue ninguna casualidad. Pero hay mucho más de lo que aparenta a simple vista. En este artículo, exploraremos las razones detrás de esta decisión de diseño y las interesantes implicaciones que tiene.
La inmutabilidad como una característica fundamental de Java String
Como dice la documentacion de Java 7: las Strings son constantes y como tal son inmutables, es decir no se pueden modificar; después de que son creados sus valores no pueden ser cambiados.
Pero la cosa no queda allí, debido a que los objetos String son inmutables las ubicaciones de memoria que hacen referencia a la misma cadena pueden ser compartidas en vez de crear nuevas cadenas en memoria logrando con esto un rendimiento mejorado porque seamos sinceros… ¿Qué aplicación de Java no usa algún texto?.
Por si se arrepentían de su decisión los desarrolladores tomaron una medida desde el inicio… el constructor de String, en su versión que recibe un String. Este constructor es una de las mayores fuentes de confusión entre programadores nuevos. A menos que una copia explicita en una nueva dirección de memoria de una cadena de texto sea necesaria, el uso de este constructor es innecesario dado que las Strings son inmutables.
System.out.println("hola" == "hola");
System.out.println("hola" == new String("hola"));
System.out.println("hola".equals("hola"));
System.out.println("hola".equals(new String("hola")));
Java String y el Patrón de Diseño Singleton
Cuando se diseñó le lenguaje se pensó que las cadenas fueran “internas”, es decir que tuvieran instancias únicas compartidas.
Recordemos que el (anti)patrón de diseño Singleton no existía en ese momento, pero los creadores pensaron en una funcionalidad similar mediante el método intern() de String. Este método habla de una “String pool” o un pozo de cadenas (o piscina de cordones si lo traducimos literal), inicialmente vacío, que es en esencia un almacén privado mantenido por la clase String donde se guardan los textos de todas las aplicaciones para la maquina virtual que las ejecute.

A diferencia de Singleton puedes tener más de una instancia de String con el mismo contenido si usas el constructor que recibe otro String.
Java String y la ropa interior provocativa
Sí, antes a las cadenas de Java se les llamaba solamente String, pero desde que llegó el lenguaje Basado en Java llamado Groovy llegó con su broma maliciosa de llamar a las cadenas de ese lenguaje como GString. Si eres exclusivamente hispanoparlante tal vez no notes la travesura, pero a alguien en algún momento se le ocurrió hacer un juego de palabras al ponerle la G de Groovy a la palabra String para que sonara como la palabra g-string que significa tanga en inglés gringo para que cada que alguien hablara de cadenas de texto en el lenguaje groovy hablara también de tangas.
Consejos clave para aprovechar al máximo Java String
Esto nos lleva a las siguientes características muy especiales del lenguaje:
- Reiniciar tu máquina virtual borrará el pool de cadenas, liberando una gran cantidad de memoria.
- Utilizar las mismas cadenas una y otra vez tendrá un impacto increíble en el desempeño de tu aplicación Java. Aprovecha esta característica para mejorar la eficiencia de tu código.
- Nunca almacenes contraseñas como cadenas, ya que representan un riesgo de seguridad. En su lugar, utiliza arreglos de caracteres que no se queden en memoria.
- Evita usar el constructor de String que recibe otra String, a menos que sea absolutamente necesario.
- Ten en cuenta que a partir de la segunda vez que se usa la misma cadena, se hará referencia al mismo objeto. Esto tiene implicaciones en cuanto al manejo de memoria y el paso por referencia en Java.
- Usa el operador + con precaución si estas usando una versión de Java menor la 8, ya que en estas versiones crea una nueva cadena. Tras usarlo una sola vez tendrás tres cadenas almacenadas en el pool y ya te imaginaras como acaba eso si tienes tu aplicación corriendo por meses.
- Evita usar
String.formattiene un pésimo desempeño.
Todo acerca del tipo String viene en la especificación del lenguaje en caso de que desees aprender más sobre el tema.
Algunas cosas más avanzadas
¡Pero eso no es todo! Aquí hay algunas ideas más avanzadas sobre Java String que te dejarán impresionado:
- Las literales de cadenas casi siempre se internan(ver dos puntos después para excepciones a esta regla) al igual que cuando uno le pasa una cadena a
String.intern() - Las cadenas en el pool de cadenas nunca serán colectadas por el recolector de basura (GC)
- Si usamos
Class.forNamepara cargar una clase las literales de cadena serán marcadas para recolección cuando la clase sea unloaded. - La llamada al constructor de String con una cadena no es una literal de cadena así que esta si será marcada para el GC
- Si concatenamos en el código se evaluará en tiempo de compilación y la cadena será internada
- En java 9+, si en tiempo de compilación se usa una cadena concatenada con una variable (no una constante) la cadena tendrá una representación especial
- Antes de Java7 el String pool estaba ubicado en el PermGen
- A partir de Java 8 la concatenación usa internamente StringBuilder para evitar crear subcadenas en el
String pooly con ello mejorar el rendimiento - A partir de Java 9 las cadenas son más ligeras, lo cual te dará mejoras de desempeño solamente con subirle la versión a tu código que tuvieras en Java 8 o inferior
Despedida
Es importante saber estos datos para mejorar como desarrollador Java, a pesar de estar mencionado en la documentación oficial, incluso ChatGPT 3.5 cuando se le enfrenta con un código que presenta problemas debido al pool de cadenas no es capaz de tomarlo en cuenta.