No podemos estar seguros de qué pensaban realmente los diseñadores de Java mientras diseñaban, String
pero solo podemos concluir estas razones en función de las ventajas que obtenemos de la inmutabilidad de cadenas, algunas de las cuales son
1. Existencia del conjunto constante de cadenas
Como se discutió en Por qué String se almacena en String Constant Pool , cada aplicación crea demasiados objetos de cadena y para evitar que JVM cree primero muchos objetos de cadena y luego los recolecte basura. JVM almacena todos los objetos de cadena en un área de memoria separada llamada Grupo constante de cadenas y reutiliza los objetos de ese grupo en caché.
Siempre que creamos un literal de cadena, JVM ve primero si ese literal ya está presente en un grupo constante o no, y si está allí, la nueva referencia comenzará a apuntar al mismo objeto en SCP.
String a = "Naresh";
String b = "Naresh";
String c = "Naresh";
En el ejemplo anterior, con objeto de cadena de valor Naresh
será creado en el SCP sólo una vez y toda referencia a
, b
, c
apuntará al mismo objeto, pero lo que si tratamos de hacer un cambio en a
por ejemplo a.replace("a", "")
.
Idealmente, a
debería tener valor , Nresh
pero debería permanecer sin cambios porque, como usuario final, solo estamos haciendo el cambio . Y sabemos , , todos apuntan al mismo objeto por lo que si hacemos un cambio enb
c
a
a
b
c
a
, otros también debe reflejar el cambio.
Pero la inmutabilidad de cadena nos salva de este escenario y, debido a la inmutabilidad del objeto de cadena, el objeto de cadena Naresh
nunca cambiará. Entonces, cuando hacemos algún cambio en a
lugar de un cambio en el objeto de cadena, Naresh
JVM crea un nuevo objeto al que se lo asigna a
y luego realiza un cambio en ese objeto.
Entonces, el conjunto de cadenas solo es posible debido a la inmutabilidad de String y si String no hubiera sido inmutable, entonces el almacenamiento en caché de los objetos de cadena y su reutilización no tendrían la posibilidad de que ninguna variable hubiera cambiado el valor y corrompido a otros.
Y es por eso que JVM lo maneja de manera muy especial y se le ha dado un área de memoria especial.
2. Seguridad del hilo
Un objeto se llama seguro para subprocesos cuando varios subprocesos están operando en él, pero ninguno de ellos puede corromper su estado y el objeto mantiene el mismo estado para cada subproceso en cualquier momento.
Como nosotros, un objeto inmutable no puede ser modificado por nadie después de su creación, lo que hace que cada objeto inmutable sea seguro para subprocesos de forma predeterminada. No necesitamos aplicarle ninguna medida de seguridad de subprocesos, como crear métodos sincronizados.
Entonces, debido a su naturaleza inmutable, el objeto de cadena puede ser compartido por múltiples hilos e incluso si está siendo manipulado por muchos hilos, no cambiará su valor.
3. Seguridad
En cada aplicación, necesitamos pasar varios secretos, por ejemplo, nombre de usuario \ contraseñas del usuario, URL de conexión y, en general, toda esta información se pasa como el objeto de cadena.
Ahora suponga que si String no hubiera sido inmutable por naturaleza, causaría una seria amenaza a la seguridad de la aplicación porque estos valores pueden modificarse y si se permite, estos podrían modificarse debido a un código escrito incorrectamente o cualquier otra persona que tener acceso a nuestras referencias variables.
4. Carga de clase
Como se discutió en Crear objetos a través de Reflection en Java con Example , podemos usarClass.forName("class_name")
método para cargar una clase en la memoria que nuevamente llama a otros métodos para hacerlo. E incluso JVM usa estos métodos para cargar clases.
Pero si ve claramente que todos estos métodos aceptan el nombre de la clase como un objeto de cadena, por lo que las cadenas se usan en la carga de clases de Java y la inmutabilidad proporciona seguridad por la que se carga la clase correcta ClassLoader
.
Supongamos que String no hubiera sido inmutable y estamos tratando de cargar los java.lang.Object
que se han cambiado org.theft.OurObject
en el medio y ahora todos nuestros objetos tienen un comportamiento que alguien puede usar para cosas no deseadas.
5. Almacenamiento en caché de HashCode
Si vamos a realizar operaciones relacionadas con el hash en cualquier objeto, debemos anular el hashCode()
método e intentar generar un código hash preciso utilizando el estado del objeto. Si se cambia el estado de un objeto, lo que significa que su código hash también debería cambiar.
Debido a que String es inmutable, el valor que tiene un objeto de cadena nunca cambiará, lo que significa que su código hash tampoco cambiará, lo que le da a la clase String la oportunidad de almacenar en caché su código hash durante la creación del objeto.
Sí, el objeto String almacena en caché su código hash en el momento de la creación del objeto, lo que lo convierte en el gran candidato para operaciones relacionadas con el hash porque el código hash no necesita calcularse nuevamente, lo que nos ahorra algo de tiempo. Es por eso que String se usa principalmente como HashMap
teclas.
Lea más sobre por qué String es inmutable y final en Java .