Sé que esto probablemente sea muy estúpido, pero muchos lugares afirman que la clase Integer en Java es inmutable, pero el siguiente código:
Integer a=3;
Integer b=3;
a+=b;
System.out.println(a);
Se ejecuta sin ningún problema para dar el resultado (esperado) 6. Así que efectivamente el valor de a ha cambiado. ¿No significa eso que Integer es mutable? Pregunta secundaria y un poco fuera de tema: "Las clases inmutables no necesitan constructores de copia". ¿Alguien quiere explicar por qué?
java
immutability
mutable
K.Steff
fuente
fuente
Respuestas:
Inmutable no significa que
a
nunca pueda igualar otro valor. Por ejemplo, tambiénString
es inmutable, pero aún puedo hacer esto:str
no se modificó, sinostr
que ahora es un objeto instanciado completamente nuevo, al igual que el suyoInteger
. Entonces, el valor dea
no cambió, pero fue reemplazado por un objeto completamente nuevo, es decirnew Integer(6)
.fuente
+=
operación.Integer.valueOf(int)
y ese método mantiene un caché deInteger
objetos. Entonces, el resultado de+=
unaInteger
variable podría ser un objeto que existía anteriormente (o incluso podría ser el mismo objeto ... en el caso dea += 0
).a
es una "referencia" a algún Integer (3), su taquigrafíaa+=b
realmente significa hacer esto:Entonces no, los enteros no son mutables, pero las variables que los señalan son *.
* Es posible tener variables inmutables, estas se denotan con la palabra clave
final
, lo que significa que la referencia no puede cambiar.fuente
Puede determinar que el objeto ha cambiado usando
System.identityHashCode()
(una mejor manera es usar simple,==
sin embargo, no es tan obvio que la referencia en lugar del valor haya cambiado)huellas dactilares
Puede ver que la "identificación" subyacente del objeto al que se
a
refiere ha cambiado.fuente
A la pregunta inicial formulada,
El entero es inmutable, por lo que lo que sucedió arriba es que 'a' ha cambiado a una nueva referencia de valor 6. El valor inicial 3 se deja sin referencia en la memoria (no se ha cambiado), por lo que se puede recolectar basura.
Si esto le sucede a una cadena, se mantendrá en el grupo (en el espacio de PermGen) durante un período más largo que los enteros, ya que espera tener referencias.
fuente
Sí Integer es inmutable.
A es una referencia que apunta a un objeto. Cuando ejecuta un + = 3, eso reasigna A para hacer referencia a un nuevo objeto Integer, con un valor diferente.
Nunca modificó el objeto original, sino que apuntó la referencia a un objeto diferente.
Lea sobre la diferencia entre objetos y referencias aquí .
fuente
Inmutable no significa que no pueda cambiar el valor de una variable. Simplemente significa que cualquier nueva asignación crea un nuevo objeto (le asigna una nueva ubicación de memoria) y luego se le asigna el valor.
Para comprender esto por sí mismo, realice la asignación de números enteros en un bucle (con el número entero declarado fuera del bucle) y observe los objetos activos en la memoria.
La razón por la que el constructor de copias no es necesario para objetos inmutables es el simple sentido común. Dado que cada asignación crea un nuevo objeto, el lenguaje técnicamente ya crea una copia, por lo que no tiene que crear otra copia.
fuente
La razón es que rara vez hay necesidad de copiar (o incluso de copiar) una instancia de una clase inmutable. La copia del objeto debe ser "igual" que el original, y si es el mismo, no debería ser necesario crearlo.
Sin embargo, existen algunas suposiciones subyacentes:
Asume que su aplicación no da ningún significado a la identidad de objeto de las instancias de la clase.
Se asume que la clase se ha sobrecargado
equals
yhashCode
que una copia de una instancia sería "igual que" el original ... de acuerdo con estos métodos.Cualquiera de esas suposiciones o ambas podrían ser falsas, y eso podría justificar la adición de un constructor de copias.
fuente
Así es como entiendo inmutable
Si int pudiera mutar, "a" imprimiría 8 pero no lo hace porque es inmutable, por eso es 3. Su ejemplo es solo una nueva asignación.
fuente
Puedo dejar en claro que Integer (y otros de su credo como Float, Short, etc.) son inmutables mediante un código de muestra simple:
El resultado llega a Hi There 100 en lugar del resultado esperado (en caso de que sb e i sean objetos mutables) Hi There 1000
Esto muestra que el objeto creado por i en main no está modificado, mientras que el sb está modificado.
Entonces StringBuilder demostró un comportamiento mutable pero no Integer.
Entonces Integer es inmutable. Por lo tanto probado
fuente
private void doStringBuilder(StringBuilder sb){ sb = new StringBuilder(); }
a continuación,sb
no se modifica.private void doInteger(Integer i){ System.out.println( i == 100 ); i=1000; System.out.println( i == 100 ); }
La salida es:
Hola adiós 1000 5000 1000 5000 d a
Entonces char es mutable, String Integer e int son inmutables.
fuente