String
é imutável *, mas isso significa apenas que você não pode alterá-lo usando sua API pública.
O que você está fazendo aqui é contornar a API normal, usando reflexão. Da mesma forma, você pode alterar os valores de enumerações, alterar a tabela de pesquisa usada na caixa automática de números inteiros etc.
Agora, a razão s1
es2
valor da mudança, é que ambos se referem à mesma cadeia interna. O compilador faz isso (conforme mencionado por outras respostas).
A razão s3
é que não foi realmente um pouco surpreendente para mim, como eu pensei que iria partilhar o value
array ( ele fez na versão anterior do Java , antes de 7u6 Java). No entanto, observando o código-fonte de String
, podemos ver que a value
matriz de caracteres para uma substring é realmente copiada (usandoArrays.copyOfRange(..)
). É por isso que permanece inalterado.
Você pode instalar um SecurityManager
, para evitar código malicioso, para fazer essas coisas. Mas lembre-se de que algumas bibliotecas dependem do uso desses tipos de truques de reflexão (normalmente ferramentas ORM, bibliotecas AOP etc.).
*) Eu escrevi inicialmente que String
s não são realmente imutáveis, apenas "imutáveis efetivamente". Isso pode ser enganoso na implementação atual de String
, onde a value
matriz é realmente marcada private final
. Ainda vale a pena notar, no entanto, que não há como declarar uma matriz em Java como imutável; portanto, deve-se tomar cuidado para não expô-la fora de sua classe, mesmo com os modificadores de acesso adequados.
Como esse tópico parece extremamente popular, aqui estão algumas leituras adicionais sugeridas: Palestra de Reflection Madness de Heinz Kabutz do JavaZone 2009, que aborda muitos dos problemas do OP, além de outras reflexões ... bem ... loucura.
Ele aborda por que isso às vezes é útil. E por que, na maioria das vezes, você deve evitá-lo. :-)