Não podemos ter certeza do que os designers de Java estavam realmente pensando ao projetar, String
mas podemos concluir esses motivos com base nas vantagens que obtemos da imutabilidade de cadeias de caracteres, algumas das quais são
1. Existência de pool constante de strings
Conforme discutido no artigo Por que a seqüência de caracteres é armazenada no pool constante de seqüências de caracteres , todo aplicativo cria muitos objetos de sequência e, a fim de salvar a JVM primeiro criando muitos objetos de sequência e depois coletando-os com lixo. A JVM armazena todos os objetos de sequência em uma área de memória separada chamada Conjunto constante de sequência e reutiliza objetos desse conjunto em cache.
Sempre que criamos um literal de cadeia, a JVM vê pela primeira vez se esse literal já está presente no pool constante ou não, e se existe, uma nova referência começará a apontar para o mesmo objeto no SCP.
String a = "Naresh";
String b = "Naresh";
String c = "Naresh";
No exemplo acima objeto string com o valor Naresh
irá ser criada no SCP apenas uma vez e todas as referências a
, b
, c
irá apontar para o mesmo objeto, mas o que se tentarmos fazer a mudança em a
eg a.replace("a", "")
.
Idealmente, a
deve ter valor , Nresh
mas deve permanecer inalterado porque, como usuário final, estamos fazendo apenas a alteração . E sabemos , , todos estão apontando o mesmo objeto para se fazer uma mudança em , outros também devem refletir a alteração.b
c
a
a
b
c
a
Mas a imutabilidade de string nos salva desse cenário e, devido à imutabilidade do objeto de string, o objeto de string Naresh
nunca será alterado. Portanto, quando fazemos alguma alteração no a
objeto de sequência, em vez de no Naresh
JVM, um novo objeto é atribuído a
e, então, fazemos a alteração nesse objeto.
Portanto, o pool de String só é possível devido à imutabilidade de String e se String não fosse imutável, o armazenamento em cache de objetos de string e a sua reutilização não teriam possibilidade, porque qualquer variável alteraria o valor e corromperia outros.
E é por isso que é tratado pela JVM de maneira muito especial e recebeu uma área de memória especial.
2. Segurança da linha
Um objeto é chamado de thread-safe quando vários threads estão operando nele, mas nenhum deles pode corromper seu estado e o objeto mantém o mesmo estado para todos os threads a qualquer momento.
Como nós, um objeto imutável não pode ser modificado por ninguém após sua criação, o que torna todos os objetos imutáveis protegidos por thread por padrão. Não precisamos aplicar nenhuma medida de segurança de thread, como a criação de métodos sincronizados.
Portanto, devido à sua natureza imutável, o objeto string pode ser compartilhado por vários threads e, mesmo que esteja sendo manipulado por muitos threads, não alterará seu valor.
3. Segurança
Em todas as aplicações, precisamos passar vários segredos, por exemplo, nome de usuário \ senhas do usuário, URLs de conexão e, em geral, todas essas informações são passadas como o objeto string.
Agora, suponha que se String não fosse imutável por natureza, isso causaria uma séria ameaça à segurança do aplicativo, porque esses valores podem ser alterados e, se for permitido, podem ser alterados devido a códigos escritos incorretamente ou a qualquer outra pessoa que tenha acesso às nossas referências de variáveis.
4. Carregamento de classe
Conforme discutido em Criando objetos através do Reflection em Java com exemplo , podemos usar o Class.forName("class_name")
método para carregar uma classe na memória que novamente chama outros métodos para fazê-lo. E até a JVM usa esses métodos para carregar classes.
Mas se você ver claramente todos esses métodos aceitam o nome da classe como um objeto string, portanto, Strings são usadas no carregamento da classe java e a imutabilidade fornece segurança pela qual a classe correta está sendo carregada ClassLoader
.
Suponha que se String não fosse imutável e estamos tentando carregar os java.lang.Object
que foram alterados para org.theft.OurObject
entre e agora todos os nossos objetos têm um comportamento que alguém pode usar para coisas indesejadas.
5. Cache de HashCode
Se pretendemos executar operações relacionadas a hash em qualquer objeto, devemos substituir o hashCode()
método e tentar gerar um código de hash preciso usando o estado do objeto. Se o estado de um objeto está sendo alterado, significa que seu código de hash também deve mudar.
Como String é imutável, o valor que um objeto de string está mantendo nunca será alterado, o que significa que seu código de hash também não será alterado, o que dá à classe String uma oportunidade de armazenar em cache seu código de hash durante a criação do objeto.
Sim, o objeto String armazena em cache seu código de hash no momento da criação do objeto, o que o torna o melhor candidato para operações relacionadas ao hash, porque o código de hash não precisa ser calculado novamente, o que economiza algum tempo. É por isso que String é usado principalmente como HashMap
chaves.
Leia mais sobre Por que a string é imutável e final em Java .