¿Por qué las cadenas son inmutables en muchos lenguajes de progtwigción?

Posible duplicado:
¿Por qué las cadenas no pueden ser mutables en Java y .NET?
¿Por qué .NET String es inmutable?

Varios idiomas han elegido esto, como C #, Java y Python. Si está destinado a ahorrar memoria o ganar eficiencia para operaciones como comparar , ¿qué efecto tiene en la concatenación y otras operaciones de modificación?

Los tipos inmutables son una buena cosa en general:

  • Funcionan mejor para concurrencia (¡no necesita bloquear algo que no puede cambiar!)
  • Reducen los errores: los objetos mutables son vulnerables a cambios cuando no lo esperas, lo que puede introducir todo tipo de errores extraños (“acción a distancia”)
  • Se pueden compartir de forma segura (es decir, con múltiples referencias al mismo objeto) que pueden reducir el consumo de memoria y mejorar la utilización de la memoria caché.
  • Compartir también hace que copiar sea una operación O (1) muy barata cuando sería O (n) si tiene que tomar una copia defensiva de un objeto mutable. Esto es un gran problema porque copiar es una operación increíblemente común (por ej., Cuando quiera pasar parámetros alrededor de …)

Como resultado, es una elección de diseño de lenguaje bastante razonable para hacer cadenas inmutables.

Algunos idiomas (particularmente los idiomas funcionales como Haskell y Clojure) van más allá y hacen que casi todo sea inmutable. Este video esclarecedor vale mucho la pena si está interesado en los beneficios de la inmutabilidad.

Hay un par de inconvenientes menores para los tipos inmutables:

  • Las operaciones que crean una cadena modificada como la concatenación son más costosas porque necesita construir nuevos objetos. Normalmente, el costo es O (n + m) para concatenar dos cadenas inmutables, aunque puede ir tan bajo como O (log (m + n)) si utiliza una estructura de datos de cadena basada en un árbol como una cuerda . Además, siempre puedes utilizar herramientas especiales como StringBuilder de Java si realmente necesitas concatenar cadenas de manera eficiente.
  • Un pequeño cambio en una cadena grande puede dar como resultado la necesidad de construir una copia completamente nueva de la cadena grande, lo que obviamente aumenta el consumo de memoria. Sin embargo, tenga en cuenta que esto no suele ser un gran problema en los lenguajes recolectados con basura, ya que la copia anterior se recogerá con bastante rapidez si no se guarda una referencia a ella.

Sin embargo, en general, las ventajas de la inmutabilidad superan ampliamente las desventajas menores. Incluso si solo está interesado en el rendimiento, las ventajas de concurrencia y la baratura de la copia harán en general que las cadenas inmutables sean mucho más efectivas que las mutables con copiado de locking y defensa.

Está principalmente destinado a evitar errores de progtwigción. Por ejemplo, las cadenas se utilizan con frecuencia como claves en hashtables. Si pudieran cambiar, la tabla hash se dañaría. Y ese es solo un ejemplo donde cambiar un dato de datos mientras lo usa causa problemas. La seguridad es otra: si se verifica si un usuario puede acceder a un archivo en una ruta determinada antes de ejecutar la operación solicitada, la secuencia que contiene la ruta no se puede modificar …

Se vuelve aún más importante cuando haces multihilo. Los datos inmutables se pueden pasar de manera segura entre hilos mientras que los datos mutables causan interminables dolores de cabeza.

Básicamente, los datos inmutables hacen que el código que funciona en él sea más fácil de razonar. Por eso, los lenguajes puramente funcionales intentan mantener todo inmutable.

En Java, no solo inmutable es String, sino todas las clases primarias de Wrapper (Integer, Double, Character, etc.). No estoy seguro de la razón exacta, pero creo que estos son los tipos de datos básicos en los que funcionan todos los esquemas de progtwigción. Si cambian, las cosas podrían volverse salvajes. Para ser más específico, usaré un ejemplo: Digamos que ha abierto una conexión de socket a un host remoto. El nombre de host sería una Cadena y el puerto sería Integer. ¿Qué ocurre si estos valores se modifican después de que se establece la conexión?

En lo que respecta al rendimiento, Java asigna memoria a estas clases desde una sección de memoria separada llamada Literal Pool, y no desde stack o Heap. Literal Pool está indexado y si usa una cadena “String” dos veces, apuntan al mismo objeto del grupo Literal.

Tener cadenas tan inmutables también permite que las nuevas referencias de cadenas sean fáciles, ya que las mismas cadenas / similares estarán disponibles en el conjunto de las cadenas previamente creadas. De esta manera, se reduce el costo de creación de objetos nuevos.