java string immutability

java - ¿Es "nuevo String()" inmutable también?



immutability (15)

La cadena es inmutable independientemente de cómo se instancia

1) La respuesta corta es , la new String() es inmutable.

Debido a que cada operación mutable posible (como replace , toLowerCase etcetra) que lleva a cabo en String no afecta la instancia original de String y le devuelve una nueva instancia .

Puede verificar esto en Javadoc para String . Cada método public de String que está expuesto devuelve una nueva instancia de String y no altera la instancia actual en la que llamó al método.

Esto es muy útil en el entorno de subprocesos múltiples ya que no tienes que pensar en la mutabilidad ( alguien cambiará el valor ) cada vez que pasas o compartes el String . String puede ser fácilmente el tipo de datos más utilizado, por lo que los diseñadores nos han bendecido a todos para no pensar en la mutabilidad cada vez y nos han ahorrado mucho dolor.

Inmutabilidad permitida String pool o caching

Es debido a la propiedad de inmutabilidad que el conjunto interno de cadenas era posible, ya que cuando se requiere el mismo valor de Cadena en otro lugar, se devuelve esa referencia inmutable. Si String hubiera sido mutable, no habría sido posible compartir String como esta para ahorrar memoria.

La inmutablidad de la cadena no se debió a la puesta en común, sino que la inmutabilidad tiene más beneficios asociados.

Interno de cadenas o agrupación es un ejemplo de patrón de diseño Flyweight

2) Sí, será internado como cualquier otra String como una String blanco también es una String igual que otras String .

Referencias

Estuve estudiando Java String por un tiempo. Las siguientes preguntas se basan en las publicaciones siguientes

Java String es especial
Inmutabilidad de String en Java

  1. Inmutabilidad: ahora, pasando por la inmutabilidad, la clase String se ha diseñado de modo que los valores en el conjunto común se puedan reutilizar en otros lugares / variables. Esto es válido si la String fue creada como

    String a = "Hello World!"; Sin embargo, si creo una cadena como

    String b = new String("Hello World!"); ¿Por qué es esto inmutable también? (¿O es eso?). Como esto tiene una memoria de pila dedicada, debería poder modificar esto sin afectar a ninguna otra variable. Entonces, por diseño, ¿había alguna otra razón por String cual String como un todo se considera inmutable? ¿O está mi suposición anterior incorrecta?

  2. Lo segundo que quería preguntar era sobre el grupo común de cadenas . Si creo un objeto de cadena como

    String c = ""; es una entrada vacía creada en el grupo?

¿Hay alguna publicación ya en estos? Si es así, ¿alguien podría compartir el enlace?


1) Inmutabilidad: la cadena será inmutable si la creas usando una forma nueva u otra por razones de seguridad

2) Sí, habrá una entrada vacía en el grupo de cadenas.

Puedes entender mejor el concepto usando el código

String s1 = new String("Test"); String s2 = new String("Test"); String s3 = "Test"; String s4 = "Test"; System.out.println(s1==s2);//false System.out.println(s1==s3);//false System.out.println(s2==s3);//false System.out.println(s4==s3);//true

Espero que esto ayude a tu consulta. Siempre puede verificar el código fuente de la clase String en caso de una mejor comprensión Enlace: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/String.java


1) La parte inmutable no se debe a la agrupación; simplemente hace que la piscina sea posible en primer lugar. Las cadenas a menudo se pasan como argumentos a otras funciones o incluso se comparten con otros hilos; Hacer cadenas inmutables fue una decisión de diseño para facilitar el razonamiento en tales situaciones. Entonces, , las String en Java son siempre inmutables, sin importar cómo las crees (ten en cuenta que es posible tener cadenas mutables en Java, pero no con la clase String ).

2) Sí. Probablemente. Realmente no estoy 100% seguro, pero ese debería ser el caso.



De la documentación de Oracle de Java :

Las cadenas son constantes; sus valores no se pueden cambiar después de que se crean .

Y otra vez:

Los búferes de cadena admiten cadenas mutables. Debido a que los objetos String son inmutables, se pueden compartir.

En términos generales: el objeto "primitivo" (o relacionado) es inmutable (por favor, acepte mi falta de formalismo).

Publicación relacionada sobre desbordamiento de pila:

Acerca del grupo de objetos : el grupo de objetos es una optimización de Java que NO está relacionada con lo inmutable también.


Esto no es estrictamente una respuesta a su pregunta, pero si detrás de su pregunta está el deseo de tener cadenas mutables que pueda manipular, debería verificar la clase StringBuilder , que implementa muchos de los mismos métodos que String pero también agrega métodos para cambiar los contenidos actuales.

Una vez que haya creado su cadena de tal manera que esté satisfecho con ella, simplemente llame a toString() para convertirla en una String ordinaria que puede pasar a las rutinas de la biblioteca y otras funciones que solo toman String s.

Además, tanto StringBuilder como String implementan la interfaz CharSequence , por lo que si desea escribir funciones en su propio código que puedan usar cadenas mutables e inmutables, puede declararlas para tomar cualquier objeto CharSequence .


La cadena es inmutable porque no le proporciona un medio para modificarla. Está diseñado para evitar cualquier alteración (es definitivo, no se supone que la matriz subyacente debe tocarse ...).

De manera idéntica, Integer es inmutable, porque no hay forma de modificarlo.

No importa cómo lo crees.


La cadena es inmutable significa que no puede cambiar el objeto en sí, sin importar cómo lo haya creado. Y en cuanto a la segunda pregunta: sí, creará una entrada.


La inmutabilidad no es una característica new , es una característica de la clase String . No tiene métodos de mutación, por lo que es inmutable.


Las bibliotecas de Java están muy optimizadas en torno a la restricción de que cualquier objeto String es inmutable, independientemente de cómo se construya ese objeto. Incluso si crea su b usando un código new , otro que pase esa instancia tratará el valor como inmutable. Este es un ejemplo del patrón Value Object, y se aplican todas las ventajas (seguridad de subprocesos, sin necesidad de hacer copias privadas).

La cadena vacía "" es un objeto String legítimo como cualquier otra cosa, simplemente no tiene contenido interno, y dado que todas las cadenas constantes en tiempo de compilación están intercaladas, prácticamente garantizaré que alguna biblioteca en tiempo de ejecución ya ha causado que sea agregado a la piscina.


Las cadenas creadas siempre serán inmutables independientemente de cómo se creen.

Respuestas a tus preguntas:

  1. La única diferencia es:
    Cuando se crea un string como - {String a = "Hello World!";} , Solo se crea un objeto .
    Y cuando se crea como - {String b = new String("Hello World!");} , Se crean dos objetos . El primero, porque ha usado la palabra clave ''nueva'' y la segunda debido a la propiedad de cadena .

  2. Si por su puesto. Habrá una entrada vacía creada en el grupo.


Tenga en cuenta que en su ejemplo, la referencia se cambia y no el objeto al que hace referencia, es decir, b como referencia puede cambiarse y referirse a un nuevo objeto. Pero ese nuevo objeto es inmutable, lo que significa que su contenido no se cambiará "después" de llamar al constructor.

Puedes cambiar una cadena usando b=b+"x"; o b=new String(b); , y el contenido de la variable a parece cambiar, pero no confunde la inmutabilidad de una referencia (aquí la variable b ) y el objeto al que se refiere (piense en punteros en C). El objeto al que apunta la referencia permanecerá sin cambios después de su creación.

Si necesita cambiar una cadena cambiando el contenido del objeto (en lugar de cambiar la referencia), puede usar StringBuffer , que es una versión mutable de String.


new String() es una expresión que produce un String ... y un String es inmutable, sin importar cómo se produce.

(Preguntar si el new String() es mutable o no, no tiene sentido. Es un código de programa, no un valor. Pero entiendo que eso no es lo que realmente quiso decir).

Si creo un objeto de cadena como String c = ""; es una entrada vacía creada en el grupo?

Sí; es decir, se crea una entrada para la cadena vacía. No hay nada especial sobre una String vacía.

(Para ser pedantes, la entrada de pool para "" se crea mucho antes de que se ejecute su código. De hecho, se crea cuando se carga su código ... o posiblemente incluso antes de eso).

Entonces, quería saber si el nuevo objeto Heap también es inmutable ...

Sí lo es. Pero la inmutabilidad es una propiedad fundamental de los objetos String. Todos los objetos String .

Verá, la API String simplemente no proporciona ningún método para cambiar una String . Entonces (aparte de algunos trucos 1 peligrosos y tontos usando la reflexión), no puedes mutar una String .

y de ser así, ¿cuál era el propósito ?.

La razón por la que Java String está diseñado como una clase inmutable es la simplicidad. Hace que sea más fácil escribir programas correctos y leer / razonar sobre el código de otras personas si la clase de cadena principal proporciona una interfaz inmutable. (O al menos, esa es la razón de esta decisión de diseño, tal como yo lo entiendo).

Siguiendo la respuesta, entiendo que otras referencias a la misma variable es una de las razones. Por favor, avíseme si estoy en lo cierto al entender esto.

No. Es más fundamental que eso. Simplemente, todos los objetos String son inmutables. No es necesario razonar un caso especial complicado para entender esto. Simplemente >> es <<.

Para el registro, si desea un objeto "string-like" mutable en Java, puede usar StringBuilder o StringBuffer . Pero estos son tipos diferentes a String.

1 - La razón por la cual estos trucos son (IMO) peligrosos y tontos es que afectan los valores de cadenas potencialmente compartidas por otras partes de su aplicación a través del grupo de cadenas. Esto puede causar caos ... de forma que el siguiente tipo que mantiene tu código tiene pocas posibilidades de localizarlo.


Es al revés, en realidad.

[...] la clase String ha sido diseñada para que los valores en el grupo común puedan reutilizarse en otros lugares / variables.

No, la clase String es inmutable, por lo que puede hacer referencia de forma segura a una instancia de la misma, sin preocuparse de que se modifique desde otra parte de su programa. Esta es la razón por la cual la agrupación es posible en primer lugar.

Por lo tanto, considere esto:

// this string literal is interned and referenced by ''a'' String a = "Hello World!"; // creates a new instance by copying characters from ''a'' String b = new String(a);

Ahora, ¿qué ocurre si simplemente creas una referencia a tu variable b recién creada?

// ''c'' now points to the same instance as ''b'' String c = b;

Imagine que pasa c (o, más específicamente, el objeto al que hace referencia) a un método en un subproceso diferente y continúa trabajando con la misma instancia en su subproceso principal. Y ahora imagine lo que sucedería si las cadenas fueran mutables.

¿Por qué es este el caso de todos modos?

Si nada más, es porque los objetos inmutables hacen que el multihilo sea mucho más simple y, por lo general, incluso más rápido. Si comparte un objeto mutable (que sería cualquier objeto con estado, con campos o propiedades mutables privadas / públicas) entre diferentes subprocesos, debe tener especial cuidado para garantizar el acceso sincronizado (mutexes, semáforos). Incluso con esto, necesita cuidados especiales para garantizar la atomicidad en todas sus operaciones. Multithreading es difícil.

En cuanto a las implicaciones de rendimiento, tenga en cuenta que copiar con frecuencia toda la cadena en una nueva instancia, para cambiar incluso un solo carácter, es en realidad más rápido que inducir un costoso cambio de contexto debido a las construcciones de sincronización necesarias para garantizar el acceso a subprocesos. Y como ha mencionado, la inmutabilidad también ofrece posibilidades de internamiento, lo que significa que realmente puede ayudar a reducir el uso de memoria.

En general, es una buena idea hacer tantas cosas inmutables como puedas .


String A = "Test" String B = "Test"

Ahora String B called "Test" .toUpperCase () which change the same object into "TEST" , so A will also be "TEST" `que no es deseable.