Eu sei que isso é provavelmente muito estúpido, mas muitos lugares afirmam que a classe Integer em Java é imutável, mas o seguinte código:
Integer a=3;
Integer b=3;
a+=b;
System.out.println(a);
Executa sem problemas, fornecendo o resultado (esperado) 6. Portanto, efetivamente, o valor de a foi alterado. Isso não significa que Integer é mutável? Questão secundária e um pouco offtopic: "Classes imutáveis não precisam de construtores de cópia". Alguém se importa em explicar por quê?
java
immutability
mutable
K.Steff
fonte
fonte
Respostas:
Imutável não significa que
a
nunca possa ser igual a outro valor. Por exemplo, tambémString
é imutável, mas ainda posso fazer isso:str
não foi alterado; em vez disso,str
é agora um objeto completamente instanciado, assim como o seuInteger
. Portanto, o valor dea
não sofreu mutação, mas foi substituído por um objeto completamente novo, isto énew Integer(6)
.fonte
+=
operação.Integer.valueOf(int)
e esse método mantém um cache deInteger
objetos. Portanto, o resultado de+=
em umaInteger
variável pode ser um objeto que existia anteriormente (ou pode até ser o mesmo objeto ... no caso dea += 0
).a
é uma "referência" a algum Integer (3), sua abreviaçãoa+=b
realmente significa fazer isto:Portanto, não, os inteiros não são mutáveis, mas as variáveis que apontam para eles são *.
* É possível ter variáveis imutáveis, estas são denotadas pela palavra-chave
final
, o que significa que a referência não pode mudar.fonte
Você pode determinar que o objeto mudou usando
System.identityHashCode()
(A melhor maneira é usar simples,==
no entanto, não é tão óbvio que a referência ao invés do valor mudou)estampas
Você pode ver que o "id" subjacente do objeto
a
ao qual se refere mudou.fonte
Para a pergunta inicial feita,
O número inteiro é imutável, então o que aconteceu acima é que 'a' mudou para uma nova referência de valor 6. O valor inicial 3 é deixado sem nenhuma referência na memória (ele não foi alterado), então pode ser coletado como lixo.
Se isso acontecer com uma String, ela se manterá no pool (no espaço PermGen) por um período maior do que os Inteiros, pois espera ter referências.
fonte
Sim, o inteiro é imutável.
A é uma referência que aponta para um objeto. Quando você executa a + = 3, isso reatribui A para fazer referência a um novo objeto Integer, com um valor diferente.
Você nunca modificou o objeto original, em vez disso, apontou a referência para um objeto diferente.
Leia sobre a diferença entre objetos e referências aqui .
fonte
Imutável não significa que você não pode alterar o valor de uma variável. Significa apenas que qualquer nova atribuição cria um novo objeto (atribui a ele um novo local de memória) e, em seguida, o valor é atribuído a ele.
Para entender isso por si mesmo, execute a atribuição de Inteiro em um loop (com o inteiro declarado fora do loop) e observe os objetos ativos na memória.
A razão pela qual o construtor de cópia não é necessário para objetos imutáveis é o simples bom senso. Como cada atribuição cria um novo objeto, a linguagem tecnicamente já cria uma cópia, portanto, você não precisa criar outra cópia.
fonte
A razão é que raramente há necessidade de copiar (ou mesmo qualquer ponto na cópia) uma instância de uma classe imutável. A cópia do objeto deve ser "igual" ao original e, se for o mesmo, não haverá necessidade de criá-lo.
No entanto, existem algumas suposições subjacentes:
Ele pressupõe que seu aplicativo não atribui nenhum significado à identidade do objeto das instâncias da classe.
Ele assume que a classe está sobrecarregada
equals
ehashCode
que uma cópia de uma instância seria "igual" ao original ... de acordo com esses métodos.Uma ou ambas as suposições podem ser falsas e isso pode justificar a adição de um construtor de cópia.
fonte
É assim que eu entendo imutável
Se int pudesse sofrer mutação, "a" imprimiria 8, mas não, porque é imutável, é por isso que é 3. Seu exemplo é apenas uma nova atribuição.
fonte
Posso deixar claro que Integer (e outras crenças como Float, Short etc) são imutáveis por um código de amostra simples:
O resultado chega a ele Hi There 100 em vez do resultado esperado (no caso de sb e i serem objetos mutáveis) Hi There 1000
Isso mostra que o objeto criado por i em principal não foi modificado, enquanto o sb foi modificado.
Portanto, StringBuilder demonstrou comportamento mutável, mas não Integer.
Portanto, o inteiro é imutável. Provado Conseqüentemente
fonte
private void doStringBuilder(StringBuilder sb){ sb = new StringBuilder(); }
entãosb
não será alterado.private void doInteger(Integer i){ System.out.println( i == 100 ); i=1000; System.out.println( i == 100 ); }
O resultado é:
Hi Bye 1000 5000 1000 5000 d a
Então char é mutável, String Integer e int são imutáveis.
fonte