Por que String é imutável em Java?

Por que String é imutável em Java?

1. Introdução

Em Java, Strings são imutáveis. Uma pergunta óbvia que prevalece bastante nas entrevistas é "Por que as seqüências de caracteres são projetadas como imutáveis ​​em Java?"

James Gosling, o criador do Java,was once asked in an interview quando se deve usar imutáveis, ao que ele responde:

Eu usaria um imutável sempre que pudesse.

Ele também apóia seu argumento afirmando recursos que a imutabilidade fornece, como cache, segurança, reutilização fácil sem replicação, etc.

Neste tutorial, exploraremos mais por que os designers da linguagem Java decidiram manterString imutável.

2. O que é um objeto imutável?

Um objeto imutável é umobject whose internal state remains constant after it has been entirely created. Isso significa que, uma vez que o objeto tenha sido atribuído a uma variável, não podemos atualizar a referência nem alterar o estado interno por qualquer meio.

Temos um artigo separado que discute objetos imutáveis ​​em detalhes. Para obter mais informações, leia o artigoImmutable Objects in Java.

3. Por queString é imutável em Java?

Os principais benefícios de manter essa classe como imutável são cache, segurança, sincronização e desempenho.

Vamos discutir como essas coisas funcionam.

3.1. Apresentar ao poolString

OString é a estrutura de dados mais amplamente usada. Armazenar em cache os literaisString e reutilizá-los economiza muito espaço de heap porque diferentes variáveisString referem-se ao mesmo objeto no poolString. O pool interno deString serve exatamente para esse propósito.

O Java String Pool éthe special memory region where Strings are stored by the JVM. ComoStrings são imutáveis ​​em Java, a JVM otimiza a quantidade de memória alocada para eles, armazenando apenas uma cópia de cadaString literal no pool. Esse processo é chamado de internação:

String s1 = "Hello World";
String s2 = "Hello World";

assertThat(s1 == s2).isTrue();

Por causa da presença do poolString no exemplo anterior, duas variáveis ​​diferentes estão apontando para o mesmo objetoString do pool, economizando assim recursos de memória cruciais.

image

Temos um artigo separado dedicado ao JavaString Pool. Para obter mais informações,head on over to that article.

3.2. Segurança

OString é amplamente utilizado em aplicativos Java para armazenar informações confidenciais, como nomes de usuário, senhas, URLs de conexão, conexões de rede, etc. Ele também é usado extensivamente por carregadores de classes JVM durante o carregamento de classes.

Portanto, proteger a classeString é crucial em relação à segurança de todo o aplicativo em geral. Por exemplo, considere este trecho de código simples:

void criticalMethod(String userName) {
    // perform security checks
    if (!isAlphaNumeric(userName)) {
        throw new SecurityException();
    }

    // do some secondary tasks
    initializeDatabase();

    // critical task
    connection.executeUpdate("UPDATE Customers SET Status = 'Active' " +
      " WHERE UserName = '" + userName + "'");
}

No snippet de código acima, digamos que recebemos um objetoString de uma fonte não confiável. Estamos fazendo todas as verificações de segurança necessárias inicialmente para verificar seString é apenas alfanumérico, seguido por mais algumas operações.

Lembre-se de que nosso método não confiável de chamada de origem ainda faz referência a esse objetouserName.

If Strings were mutable, then by the time we execute the update, we can’t be sure that the String we received, even after performing security checks, would be safe. O método do chamador não confiável ainda tem a referência e pode alterar oString entre as verificações de integridade. Assim, tornando nossa consulta propensa a injeções de SQL nesse caso. Portanto,Strings mutável pode levar à degradação da segurança ao longo do tempo.

Também pode acontecer queStringuserName esteja visível para outro encadeamento, que pode então alterar seu valor após a verificação de integridade.

Em geral, a imutabilidade vem em nosso socorro neste caso, porque é mais fácil operar com código confidencial quando os valores não mudam porque há menos intercalações de operações que podem afetar o resultado.

3.3. Sincronização

Ser imutável automaticamente torna o segmentoString seguro, pois eles não serão alterados quando acessados ​​de vários segmentos.

Portanto,immutable objects, in general, can be shared across multiple threads running simultaneously. They’re also thread-safe porque se um encadeamento alterar o valor, em vez de modificar o mesmo, um novoString seria criado no poolString. Portanto,Strings são seguros para multithreading.

3.4. Cache de Hashcode

Como os objetosString são usados ​​abundantemente como uma estrutura de dados, eles também são amplamente usados ​​em implementações de hash comoHashMap,HashTable,HashSet, etc. Ao operar sobre essas implementações de hash, o métodohashCode() é chamado com bastante frequência para bucketing.

A imutabilidade garanteStrings que seu valor não mudará. Entãothe hashCode() method is overridden in String class to facilitate caching, such that the hash is calculated and cached during the first hashCode() call and the same value is returned ever since.

Isso, por sua vez, melhora o desempenho de coleções que usam implementações de hash quando operadas com objetosString.

Por outro lado,Strings mutável produziria dois hashcodes diferentes no momento da inserção e recuperação se o conteúdo deString fosse modificado após a operação, potencialmente perdendo o objeto de valor emMap.

3.5. atuação

Como vimos anteriormente, o poolString existe porqueStrings são imutáveis. Por sua vez, melhora o desempenho ao salvar memória heap e acesso mais rápido de implementações de hash quando operado comStrings.

ComoString é a estrutura de dados mais amplamente usada, melhorar o desempenho deString tem um efeito considerável na melhoria do desempenho de todo o aplicativo em geral.

4. Conclusão

Por meio deste artigo, podemos concluir queStrings are immutable precisely so that their references can be treated as a normal variable and one can pass them around, between methods and across threads, without worrying about whether the actual String object it’s pointing to will change.

Também aprendemos quais podem ser os outros motivos que levaram os designers de linguagemJava a tornar esta classe imutável.