¿Por qué las cadenas no pueden ser mutables en Java y .NET?

190

¿Por qué decidieron hacer Stringinmutables en Java y .NET (y algunos otros lenguajes)? ¿Por qué no lo hicieron mutable?

chrissie1
fuente
13
Pensé lo mismo, pero revisé la ubicación de los carteles originales y descubrí que son de Bélgica. Dado que esto significa que no es probable que sean hablantes nativos de inglés. Junto con el hecho de que la mayoría de los nativos tienen un conocimiento flojo del idioma, decidí dejarla un poco.
belugabob
8
Gracias belugabob, pero no soy ella, soy él. Aparentemente, las personas no consideran las diferencias culturales.
chrissie1
77
Mis disculpas - chrissie es (generalmente) un nombre de niña en el Reino Unido - me hace víctima de otra diferencia cultural :-)
belugabob
Solo una nota, en .NET Stringes realmente mutable internamente. StringBuilderen .NET 2.0 muta una cadena . Lo dejaré aquí.
Alvin Wong
En realidad, las cadenas .NET son mutables. Y ni siquiera es un gran truco.
Bitterblue

Respuestas:

204

Según Effective Java , capítulo 4, página 73, 2a edición:

"Hay muchas buenas razones para esto: las clases inmutables son más fáciles de diseñar, implementar y usar que las clases mutables. Son menos propensas a errores y son más seguras".

[...]

" Los objetos inmutables son simples. Un objeto inmutable puede estar exactamente en un estado, el estado en el que fue creado. Si se asegura de que todos los constructores establezcan invariantes de clase, entonces se garantiza que estos invariantes permanecerán verdaderos todo el tiempo, con sin esfuerzo de tu parte.

[...]

Los objetos inmutables son inherentemente seguros para subprocesos; No requieren sincronización. No pueden ser corrompidos por múltiples hilos que acceden a ellos simultáneamente. Este es, de lejos, el enfoque más fácil para lograr la seguridad del hilo. De hecho, ningún hilo puede observar ningún efecto de otro hilo en un objeto inmutable. Por lo tanto, los objetos inmutables se pueden compartir libremente

[...]

Otros pequeños puntos del mismo capítulo:

No solo puede compartir objetos inmutables, sino que también puede compartir sus elementos internos.

[...]

Los objetos inmutables son grandes bloques de construcción para otros objetos, ya sean mutables o inmutables.

[...]

La única desventaja real de las clases inmutables es que requieren un objeto separado para cada valor distinto.

FLUFF PRINCESA
fuente
22
Lea la segunda oración de mi respuesta: las clases inmutables son más fáciles de diseñar, implementar y usar que las clases mutables. Son menos propensos a errores y son más seguros.
PRINCESS FLUFF
55
@PRINCESSFLUFF Agregaría que compartir cadenas mutables es peligroso incluso en un solo hilo. Por ejemplo, la copia de un informe: report2.Text = report1.Text;. Luego, en otro lugar, modificar el texto: report2.Text.Replace(someWord, someOtherWord);. Esto cambiaría el primer informe y el segundo.
phoog
10
@ Sam no preguntó "por qué no pueden ser mutables", preguntó "por qué decidieron hacer inmutables", lo que esto responde perfectamente.
James
1
@PRINCESSFLUFF Esta respuesta no aborda las cadenas específicamente. Esa fue la pregunta de los OP. Es muy frustrante: esto sucede todo el tiempo en SO y también con las preguntas de inmutabilidad de String. La respuesta aquí habla sobre los beneficios generales de la inmutabilidad. Entonces, ¿por qué no todos los tipos son inmutables? ¿Puedes regresar y abordar String?
Howiecamp
@Howiecamp Creo que está implícito en la respuesta que las cadenas podrían haber sido mutables (nada impide que exista una hipotética clase de cadena mutable). Simplemente decidieron no hacerlo de esa manera por simplicidad y porque cubrían el 99% de los casos de uso. Todavía proporcionaron StringBuilder para los otros casos del 1%.
Daniel García Rubio
102

Hay al menos dos razones.

Primero: seguridad http://www.javafaq.nu/java-article1060.html

La razón principal por la que String se volvió inmutable fue la seguridad. Mira este ejemplo: tenemos un método para abrir archivos con verificación de inicio de sesión. Pasamos una Cadena a este método para procesar la autenticación que es necesaria antes de que la llamada se pase al sistema operativo. Si String era mutable, de alguna manera era posible modificar su contenido después de la verificación de autenticación antes de que el sistema operativo reciba la solicitud del programa, entonces es posible solicitar cualquier archivo. Por lo tanto, si tiene derecho a abrir un archivo de texto en el directorio de usuarios pero luego sobre la marcha cuando de alguna manera logra cambiar el nombre del archivo, puede solicitar abrir el archivo "passwd" o cualquier otro. Luego, se puede modificar un archivo y será posible iniciar sesión directamente en el sistema operativo.

Segundo: eficiencia de la memoria http://hikrish.blogspot.com/2006/07/why-string-class-is-immutable.html

JVM mantiene internamente el "conjunto de cadenas". Para lograr la eficiencia de la memoria, JVM referirá el objeto String del grupo. No creará los nuevos objetos de cadena. Entonces, cada vez que cree un nuevo literal de cadena, JVM verificará en el grupo si ya existe o no. Si ya está presente en el grupo, solo proporcione la referencia al mismo objeto o cree el nuevo objeto en el grupo. Habrá muchas referencias que apuntan a los mismos objetos String, si alguien cambia el valor, afectará a todas las referencias. Entonces, el sol decidió hacerlo inmutable.

Jorge Ferreira
fuente
Es un buen punto sobre la reutilización, y especialmente cierto si usa String.intern (). Hubiera sido posible reutilizar sin hacer que todas las cadenas sean inmutables, pero la vida tiende a complicarse en ese punto.
jsight
3
Ninguno de esos parece ser un motivo terriblemente válido para mí hoy en día.
Brian Knoblauch
1
No estoy demasiado convencido por el argumento de la eficiencia de la memoria (es decir, cuando dos o más objetos String comparten los mismos datos, y uno se modifica, entonces ambos se modifican). Los objetos CString en MFC evitan eso mediante el recuento de referencias.
RobH
77
la seguridad no es realmente parte de la Raison d'être para cadenas inmutables: su sistema operativo copiará cadenas en buffers en modo kernel y realizará una verificación de acceso allí, para evitar ataques de sincronización. Realmente se trata de seguridad y rendimiento del hilo :)
snemarch
1
El argumento de eficiencia de memoria tampoco funciona. En un lenguaje nativo como C, las constantes de cadena son simplemente punteros a los datos en la sección de datos inicializados; de todos modos, son de solo lectura / inmutables. "si alguien cambia el valor" - de nuevo, las cadenas del grupo son de solo lectura de todos modos.
wj32
57

En realidad, las razones por las que las cadenas son inmutables en Java no tienen mucho que ver con la seguridad. Las dos razones principales son las siguientes:

Thead Safety:

Las cadenas son un tipo de objeto extremadamente utilizado. Por lo tanto, está más o menos garantizado para ser utilizado en un entorno de subprocesos múltiples. Las cadenas son inmutables para garantizar que sea seguro compartir cadenas entre subprocesos. Tener cadenas inmutables asegura que al pasar cadenas del hilo A a otro hilo B, el hilo B no puede modificar inesperadamente la cadena del hilo A.

Esto no solo ayuda a simplificar la tarea ya bastante complicada de la programación multiproceso, sino que también ayuda con el rendimiento de las aplicaciones multiproceso. El acceso a objetos mutables debe sincronizarse de alguna manera cuando se puede acceder desde múltiples hilos, para asegurarse de que un hilo no intente leer el valor de su objeto mientras otro hilo lo está modificando. La sincronización adecuada es difícil de hacer correctamente para el programador y costosa en tiempo de ejecución. Los objetos inmutables no se pueden modificar y, por lo tanto, no necesitan sincronización.

Actuación:

Si bien se ha mencionado el internamiento de cadenas, solo representa una pequeña ganancia en la eficiencia de la memoria para los programas Java. Solo los literales de cadena están internados. Esto significa que solo las cadenas que son iguales en su código fuente compartirán el mismo objeto de cadena. Si su programa crea dinámicamente cadenas que son iguales, se representarán en diferentes objetos.

Más importante aún, las cadenas inmutables les permiten compartir sus datos internos. Para muchas operaciones de cadena, esto significa que la matriz subyacente de caracteres no necesita copiarse. Por ejemplo, supongamos que desea tomar los cinco primeros caracteres de String. En Java, llamarías a myString.substring (0,5). En este caso, lo que hace el método substring () es simplemente crear un nuevo objeto String que comparta el carácter subyacente de myString [] pero quién sabe que comienza en el índice 0 y termina en el índice 5 de ese carácter []. Para poner esto en forma gráfica, terminaría con lo siguiente:

 |               myString                  |
 v                                         v
"The quick brown fox jumps over the lazy dog"   <-- shared char[]
 ^   ^
 |   |  myString.substring(0,5)

Esto hace que este tipo de operaciones sea extremadamente barato, y O (1) ya que la operación no depende de la longitud de la cadena original ni de la longitud de la subcadena que necesitamos extraer. Este comportamiento también tiene algunos beneficios de memoria, ya que muchas cadenas pueden compartir su carácter subyacente [].

LordOfThePigs
fuente
66
La implementación de subcadenas como referencias que comparten el subyacente char[]es una decisión de diseño bastante cuestionable. Si lee un archivo completo en una sola cadena y mantiene una referencia a solo una subcadena de 1 carácter, todo el archivo deberá mantenerse en la memoria.
Gabe
55
Exactamente, me encontré con ese problema en particular al crear un rastreador de sitios web que solo necesitaba extraer algunas palabras de toda la página. El código HTML de toda la página estaba en la memoria, y debido a que la subcadena compartía el carácter [], guardé todo el código HTML aunque solo necesitaba unos pocos bytes. Una solución alternativa para eso es usar una nueva Cadena (original.substring (.., ..)), el constructor de Cadena (Cadena) hace una copia del rango relevante de la matriz subyacente.
LordOfThePigs
1
Un apéndice para cubrir los cambios posteriores: desde Jave 7, String.substring()realiza una copia completa, para evitar los problemas mencionados en los comentarios anteriores. En Java 8, los dos campos que permiten char[]compartir, a saber , county offset, se eliminan, lo que reduce la huella de memoria de las instancias de String.
Christian Semrau
Estoy de acuerdo con la parte de Thead Safety, pero dudo del caso de la subcadena.
Gqqnbig
@LoveRight: luego verifique el código fuente de java.lang.String ( grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/… ), ha sido así hasta Java 6 (que era actual cuando se escribió esta respuesta). Aparentemente he cambiado en Java 7.
LordOfThePigs
28

Seguridad y rendimiento del hilo. Si una cadena no se puede modificar, es seguro y rápido pasar una referencia entre múltiples hilos. Si las cadenas fueran mutables, siempre tendría que copiar todos los bytes de la cadena a una nueva instancia o proporcionar sincronización. Una aplicación típica leerá una cadena 100 veces por cada vez que sea necesario modificarla. Ver wikipedia sobre inmutabilidad .

Matt Howells
fuente
11

Uno realmente debería preguntarse, "¿por qué X debería ser mutable?" Es mejor pasar por defecto a la inmutabilidad, debido a los beneficios ya mencionados por Princess Fluff . Debería ser una excepción que algo sea mutable.

Desafortunadamente, la mayoría de los lenguajes de programación actuales tienen por defecto la mutabilidad, pero es de esperar que en el futuro el valor predeterminado sea más inmutabilidad (consulte la Lista de deseos para el próximo lenguaje de programación principal ).

Esko Luontola
fuente
7

¡Guauu! No puedo creer la información errónea aquí.StringS ser inmutables no tienen nada con seguridad. Si alguien ya tiene acceso a los objetos en una aplicación en ejecución (lo que debería suponerse si está tratando de protegerse contra alguien que `` piratea '' Stringen su aplicación), seguramente habrá muchas otras oportunidades disponibles para piratear.

Es una idea bastante novedosa que la inmutabilidad de String abordar problemas de subprocesos. Hmmm ... Tengo un objeto que está siendo cambiado por dos hilos diferentes. ¿Cómo resuelvo esto? sincronizar el acceso al objeto? Naawww ... no permitamos que nadie cambie el objeto en absoluto, ¡eso solucionará todos nuestros problemas de concurrencia desordenados! De hecho, hagamos que todos los objetos sean inmutables, y luego podemos eliminar la construcción sincronizada del lenguaje Java.

La verdadera razón (señalada por otros arriba) es la optimización de la memoria. Es bastante común en cualquier aplicación que el mismo literal de cadena se use repetidamente. Es tan común, de hecho, que hace décadas, muchos compiladores hicieron la optimización de almacenar solo una instancia de un Stringliteral. El inconveniente de esta optimización es que el código de tiempo de ejecución que modifica un Stringliteral introduce un problema porque está modificando la instancia para todos los demás códigos que lo comparten. Por ejemplo, no sería bueno que una función en algún lugar de una aplicación cambie el Stringliteral "dog"a "cat". A printf("dog")daría como resultado literales (es decir, los haría inmutables). Algunos compiladores (con soporte del sistema operativo) lo lograrían colocando"cat" ser escrito en stdout. Por esa razón, tenía que haber una forma de protegerse contra el código que intenta cambiarStringString literal en un segmento especial de memoria de solo lectura que causaría un error de memoria si se realizara un intento de escritura.

En Java esto se conoce como pasantía. El compilador de Java aquí solo sigue una optimización de memoria estándar realizada por los compiladores durante décadas. Y para abordar el mismo problema de que estos Stringliterales se modifiquen en tiempo de ejecución, Java simplemente hace que la Stringclase sea inmutable (es decir, no le proporciona configuradores que le permitan cambiar el Stringcontenido). Strings no tendría que ser inmutable si Stringno ocurriera la internación de literales.

deHaar
fuente
3
Estoy totalmente en desacuerdo sobre la inmutabilidad y el comentario de subprocesos, me parece que no estás entendiendo el punto allí. Y si Josh Bloch, uno de los implementadores de Java, dice que ese fue uno de los problemas de diseño, ¿cómo puede ser eso información errónea?
javashlook
1
La sincronización es costosa. Las referencias a objetos mutables deben sincronizarse, no así para inmutable. Esa es una razón para hacer que todos los objetos sean inmutables a menos que tengan que ser mutables. Las cadenas pueden ser inmutables y, por lo tanto, hacerlo las hace más eficientes en varios subprocesos.
David Thornley el
55
@ Jim: la optimización de la memoria no es la razón 'LA', es la razón 'A'. La seguridad de subprocesos también es una razón 'A', porque los objetos inmutables son inherentemente seguros para subprocesos y no requieren sincronización costosa, como mencionó David. La seguridad del hilo es en realidad un efecto secundario de un objeto inmutable. Puede pensar en la sincronización como una forma de hacer que el objeto sea "temporalmente" inmutable (ReaderWriterLock lo hará de solo lectura, y un bloqueo regular lo hará inaccesible por completo, lo que por supuesto también lo hace inmutable).
Triynko el
1
@DavidThornley: la creación de múltiples rutas de referencia independientes para un poseedor de valor mutable lo convierte efectivamente en una entidad y hace que sea mucho más difícil razonar incluso al margen de los problemas de subprocesos. En general, los objetos mutables son más eficientes que los inmutables en los casos en que exista exactamente una ruta de referencia para cada uno, pero los objetos inmutables permiten que el contenido de los objetos se comparta de manera eficiente al compartir referencias. El mejor patrón está ejemplificado por Stringy StringBuffer, pero desafortunadamente pocos tipos siguen ese modelo.
supercat
7

String no es un tipo primitivo, pero normalmente desea usarlo con semántica de valores, es decir, como un valor.

Un valor es algo en lo que puede confiar no cambiará a sus espaldas. Si escribe: String str = someExpr(); No quiere que cambie a menos que USTED haga algo con str.

Stringcomo Objecttiene una semántica de puntero natural, para obtener una semántica de valor también debe ser inmutable.

deHaar
fuente
7

Un factor es que, si los Strings fueran mutables, los objetos que los almacenan Stringdeberían tener cuidado de almacenar copias, para que sus datos internos no cambien sin previo aviso. Dado que los Strings son un tipo bastante primitivo como los números, es bueno cuando uno puede tratarlos como si fueran pasados ​​por valor, incluso si son pasados ​​por referencia (lo que también ayuda a ahorrar en memoria).

Evan DiBiase
fuente
6

Sé que esto es un golpe, pero ... ¿Son realmente inmutables? Considera lo siguiente.

public static unsafe void MutableReplaceIndex(string s, char c, int i)
{
    fixed (char* ptr = s)
    {
        *((char*)(ptr + i)) = c;
    }
}

...

string s = "abc";
MutableReplaceIndex(s, '1', 0);
MutableReplaceIndex(s, '2', 1);
MutableReplaceIndex(s, '3', 2);
Console.WriteLine(s); // Prints 1 2 3

Incluso podría convertirlo en un método de extensión.

public static class Extensions
{
    public static unsafe void MutableReplaceIndex(this string s, char c, int i)
    {
        fixed (char* ptr = s)
        {
            *((char*)(ptr + i)) = c;
        }
    }
}

Lo que hace que el siguiente trabajo

s.MutableReplaceIndex('1', 0);
s.MutableReplaceIndex('2', 1);
s.MutableReplaceIndex('3', 2);

Conclusión: están en un estado inmutable que es conocido por el compilador. Por supuesto, lo anterior solo se aplica a cadenas .NET ya que Java no tiene punteros. Sin embargo, una cadena puede ser completamente mutable usando punteros en C #. No se trata de cómo se deben utilizar los punteros, si tienen un uso práctico o si se usan de manera segura; Sin embargo, es posible, doblando así toda la regla "mutable". Normalmente no puede modificar un índice directamente de una cadena y esta es la única forma. Hay una manera de evitar esto al no permitir instancias de puntero de cadenas o hacer una copia cuando se apunta a una cadena, pero tampoco se hace, lo que hace que las cadenas en C # no sean completamente inmutables.

Bauss
fuente
1
+1. Las cadenas .NET no son realmente inmutables; de hecho, esto se hace todo el tiempo en las clases String y StringBuilder por razones de rendimiento.
James Ko
3

Para la mayoría de los propósitos, una "cadena" es (usada / tratada como / pensada / asumida como) una unidad atómica significativa , como un número .

Por lo tanto, preguntar por qué los caracteres individuales de una cadena no son mutables es como preguntar por qué los bits individuales de un entero no son mutables.

Deberías saber por qué. Solo piensa en ello.

Odio decirlo, pero desafortunadamente estamos debatiendo esto porque nuestro idioma apesta, y estamos tratando de usar una sola palabra, cadena , para describir un concepto o clase de objeto complejo y contextualizado.

Realizamos cálculos y comparaciones con "cadenas" similares a las que hacemos con los números. Si las cadenas (o enteros) fueran mutables, tendríamos que escribir un código especial para bloquear sus valores en formas locales inmutables para realizar cualquier tipo de cálculo de manera confiable. Por lo tanto, es mejor pensar en una cadena como un identificador numérico, pero en lugar de tener 16, 32 o 64 bits de longitud, podría tener cientos de bits de longitud.

Cuando alguien dice "cuerda", todos pensamos en cosas diferentes. Aquellos que lo consideran simplemente como un conjunto de personajes, sin un propósito particular en mente, por supuesto se horrorizarán de que alguien simplemente haya decidido que no deberían poder manipular a esos personajes. Pero la clase "string" no es solo un conjunto de caracteres. Es un STRING, no un char[]. Hay algunos supuestos básicos sobre el concepto al que nos referimos como una "cadena", y generalmente se puede describir como una unidad atómica significativa de datos codificados como un número. Cuando la gente habla de "manipular cadenas", tal vez realmente están hablando de manipular personajes para construir cadenas , y un StringBuilder es excelente para eso.

Considere por un momento cómo sería si las cuerdas fueran mutables. La siguiente función API podría ser engañada para que devuelva información para un usuario diferente si la cadena de nombre de usuario mutable es modificada intencionalmente o no por otro hilo mientras esta función la está utilizando:

string GetPersonalInfo( string username, string password )
{
    string stored_password = DBQuery.GetPasswordFor( username );
    if (password == stored_password)
    {
        //another thread modifies the mutable 'username' string
        return DBQuery.GetPersonalInfoFor( username );
    }
}

La seguridad no se trata solo de 'control de acceso', también se trata de 'seguridad' y 'garantía de corrección'. Si un método no puede escribirse fácilmente y depender de él para realizar un cálculo simple o una comparación confiable, entonces no es seguro llamarlo, pero sería seguro cuestionar el lenguaje de programación en sí.

Triynko
fuente
En C #, una cadena es mutable por su puntero (uso unsafe) o simplemente por reflexión (puede obtener el campo subyacente fácilmente). Esto hace que el punto de seguridad sea nulo, ya que cualquiera que intencionalmente quiera cambiar una cadena, puede hacerlo con bastante facilidad. Sin embargo, proporciona seguridad a los programadores: a menos que haga algo especial, la cadena se garantiza inmutable (¡pero no es segura para subprocesos!).
Abel el
Sí, puede cambiar los bytes de cualquier objeto de datos (cadena, int, etc.) a través de punteros. Sin embargo, estamos hablando de por qué la clase de cadena es inmutable en el sentido de que no tiene métodos públicos incorporados para modificar sus caracteres. Estaba diciendo que una cadena es muy parecida a un número porque manipular caracteres individuales no tiene más sentido que manipular bits individuales de un número (cuando se trata una cadena como un token completo (no como una matriz de bytes) y un número como un valor numérico (no como un campo de bits) Estamos hablando a nivel de objeto conceptual, no a nivel de sub-objeto..
Triynko
2
Y solo para aclarar, los punteros en el código orientado a objetos son inherentemente inseguros, exactamente porque eluden las interfaces públicas definidas para una clase. Lo que estaba diciendo era que una función podría ser fácilmente engañada si la interfaz pública de una cadena permitía que otros hilos la modificaran. Por supuesto, siempre se puede engañar accediendo a los datos directamente con punteros, pero no tan fácil o involuntariamente.
Triynko el
1
Los 'punteros en código orientado a objetos son intrínsecamente inseguros' a menos que los llame referencias . Las referencias en Java no son diferentes a los punteros en C ++ (solo la aritmética de punteros está deshabilitada). Un concepto diferente es la administración de memoria que puede administrarse o ser manual, pero eso es algo diferente. Podría tener una semántica de referencia (punteros sin aritmética) sin tener GC (lo contrario sería más difícil en el sentido de que la semántica de la accesibilidad sería más difícil de limpiar, pero no inviable)
David Rodríguez - dribeas
La otra cosa es que si las cadenas son casi inmutables, pero no del todo (no sé suficiente CLI aquí), eso puede ser realmente malo por razones de seguridad. En algunas implementaciones de Java anteriores, podría hacer eso, y encontré un fragmento de código que lo usó para internalizar cadenas (intente localizar otra cadena interna que tenga el mismo valor, comparta el puntero, elimine el bloque de memoria anterior) y use la puerta trasera para reescribir el contenido de la cadena forzando un comportamiento incorrecto en una clase diferente. (Considere reescribir "SELECT *" a "DELETE")
David Rodríguez - dribeas
3

La inmutabilidad no está tan ligada a la seguridad. Para eso, al menos en .NET, obtienes elSecureString clase.

Edición posterior: en Java encontrarás GuardedStringuna implementación similar.

Andrei Rînea
fuente
2

La decisión de tener una cadena mutable en C ++ causa muchos problemas, vea este excelente artículo de Kelvin Henney sobre Mad COW Disease .

VACA = Copiar al escribir.

Motti
fuente
2

Es una compensación. Strings ir a la Stringpiscina y cuando crea múltiples idénticosString s comparten la misma memoria. Los diseñadores pensaron que esta técnica de ahorro de memoria funcionaría bien para el caso común, ya que los programas tienden a trabajar mucho en las mismas cadenas.

La desventaja es que las concatenaciones generan muchos Strings adicionales que solo son transitorios y simplemente se convierten en basura, lo que en realidad perjudica el rendimiento de la memoria. Tiene StringBuffery StringBuilder(en Java, StringBuildertambién está en .NET) para preservar la memoria en estos casos.

aaronroyer
fuente
1
Tenga en cuenta que el "conjunto de cadenas" no se usa automáticamente para TODAS las cadenas a menos que use explícitamente las cadenas "inter ()" ed.
jsight
2

Strings en Java no son realmente inmutables, puede cambiar sus valores utilizando la reflexión y / o la carga de clases. No debe depender de esa propiedad por seguridad. Para ver ejemplos, ver: Truco de magia en Java

deHaar
fuente
1
Creo que solo podrá hacer tales trucos si su código se ejecuta con plena confianza, por lo tanto, no hay pérdida de seguridad. También podría usar JNI para escribir directamente en la ubicación de la memoria donde se almacenan las cadenas.
Antoine Aubry
En realidad, creo que puedes cambiar cualquier objeto inmutable por reflexión.
Gqqnbig
0

La inmutabilidad es buena. Ver Java efectivo. Si tuviera que copiar una Cadena cada vez que la pasara, sería un código propenso a errores. También tiene confusión sobre qué modificaciones afectan qué referencias. De la misma manera que Integer debe ser inmutable para comportarse como int, las cadenas deben comportarse como inmutables para actuar como primitivas. En C ++, pasar cadenas por valor hace esto sin mención explícita en el código fuente.

Tom Hawtin - tackline
fuente
0

Hay una excepción para casi todas las reglas:

using System;
using System.Runtime.InteropServices;

namespace Guess
{
    class Program
    {
        static void Main(string[] args)
        {
            const string str = "ABC";

            Console.WriteLine(str);
            Console.WriteLine(str.GetHashCode());

            var handle = GCHandle.Alloc(str, GCHandleType.Pinned);

            try
            {
                Marshal.WriteInt16(handle.AddrOfPinnedObject(), 4, 'Z');

                Console.WriteLine(str);
                Console.WriteLine(str.GetHashCode());
            }
            finally
            {
                handle.Free();
            }
        }
    }
}
Lu4
fuente
-1

Es en gran parte por razones de seguridad. Es mucho más difícil asegurar un sistema si no puede confiar en que sus Strings son a prueba de manipulaciones.

jsight
fuente
1
¿Puede dar un ejemplo de lo que quiere decir con "a prueba de manipulaciones"? Esta respuesta se siente realmente fuera de contexto.
Gergely Orosz