Por que a String é imutável em Java?

Fui perguntado em uma entrevista porque String é imutável

Eu respondi assim:

Quando criamos uma string em java como String s1="hello"; então um object será criado no conjunto de strings (hello) e s1 estará apontando para hello. Agora, se novamente fizermos String s2="hello"; então outro object não será criado, mas s2 apontará para hello porque a JVM primeiro verificará se o mesmo object está presente no conjunto de cadeias de caractere ou não. Se não estiver presente, apenas um novo será criado ou não.

Agora, se o java permitir string mutable, se mudarmos s1 para hello world então s2 value também será hello world então java String é imutável.

Qualquer corpo pode me dizer se minha resposta está certa ou errada ?

   

String é imutável por vários motivos, aqui está um resumo:

  • Segurança : os parâmetros são tipicamente representados como String em conexões de rede, urls de conexão de database, nomes de usuário / senhas, etc. Se fosse mutável, esses parâmetros poderiam ser facilmente alterados.
  • Sincronização e simultaneidade: tornar o String immutable automaticamente torna o thread seguro, resolvendo os problemas de synchronization.
  • Armazenamento em cache : quando o compilador otimiza seus objects String, ele vê que, se dois objects tiverem o mesmo valor (a = “teste” eb = “teste”), você precisará de apenas um object string (para aeb, esses dois apontar para o mesmo object).
  • Carregamento de class : String é usado como argumentos para o carregamento de classs. Se mutável, pode resultar em uma class errada sendo carregada (porque objects mutáveis ​​mudam de estado).

Dito isto, a imutabilidade do String só significa que você não pode alterá-lo usando sua API pública. Você pode de fato ignorar a API normal usando reflection. Veja a resposta aqui .

No seu exemplo, se String for mutável, considere o seguinte exemplo:

  String a="stack"; System.out.println(a);//prints stack a.setValue("overflow"); System.out.println(a);//if mutable it would print overflow 

Os Desenvolvedores de Java decidem que as Strings são imutáveis ​​devido ao seguinte design, eficiência e segurança dos aspectos.

As Sequências de Design são criadas em uma área de memory especial no heap Java, conhecida como “Conjunto Interno de Cadeias”. Enquanto você cria uma nova String (Não no caso de usar o construtor String () ou qualquer outra function String que use internamente o construtor String () para criar um novo object String; construtor String () sempre cria uma nova string constante no conjunto a menos que nós chame o método intern () ) variable ele pesquisa o pool para verificar se ele já existe. Se existir, retorne a referência do object String existente. Se a Cadeia não for imutável, alterar a Cadeia com uma referência levará ao valor errado para as outras referências.

De acordo com este artigo no DZone:

O Security String é amplamente usado como parâmetro para muitas classs java, por exemplo, conexão de rede, abertura de arquivos, etc. Se String não fosse imutável, uma conexão ou arquivo seria alterado e levaria a grave ameaça à segurança. Strings mutáveis ​​também podem causar problemas de segurança no Reflection, pois os parâmetros são strings.

Eficiência O hashcode da string é freqüentemente usado em Java. Por exemplo, em um HashMap. Ser imutável garante que o hashcode será sempre o mesmo, para que possa ser armazenado em cache sem se preocupar com as alterações. Isso significa que não há necessidade de calcular o código hash toda vez que ele é usado.

Razão mais importante segundo este artigo no DZone:

String Constant Pool … Se string for mutável, mudar a string com uma referência levará ao valor errado para as outras referências.

Segurança

A string é amplamente usada como parâmetro para muitas classs java, por exemplo, conexão de rede, abertura de arquivos, etc. Se String não fosse imutável, uma conexão ou arquivo seria alterado e levaria a grave ameaça à segurança. …

Espero que isso ajude você.

Não podemos ter certeza do que os designers de Java realmente pensaram ao projetar String mas só podemos concluir essas razões com base nas vantagens que obtemos da imutabilidade das cordas. Algumas delas são

1. Existência de Piscina Constante de Cordas

Como discutido em Por que String é armazenada no artigo String Constant Pool , cada aplicativo cria muitos objects de string e para salvar a JVM de primeiro criar muitos objects de string e depois coletá-los como lixo. A JVM armazena todos os objects de cadeia de caracteres em uma área de memory separada denominada Conjunto de constantes de cadeia e reutiliza objects desse conjunto armazenado em cache.

Sempre que criamos uma string literal, a JVM primeiro vê se esse literal já está presente no conjunto constante ou não e, se estiver lá, uma nova referência começará a apontar para o mesmo object no SCP.

 String a = "Naresh"; String b = "Naresh"; String c = "Naresh"; 

No exemplo acima, o object string com o valor Naresh será criado no SCP apenas uma vez e toda referência a , b , c apontará para o mesmo object, mas e se tentarmos fazer uma alteração em a exemplo a.replace("a", "") .

Idealmente, a deve ter o valor Nresh mas b , c deve permanecer inalterado, porque como usuário final, estamos fazendo a mudança em a único. E sabemos que todos estão apontando o mesmo object, então, se fizermos uma mudança em a , outros também devem refletir a mudança.

Mas a imutabilidade das cordas nos salva deste cenário e, devido à imutabilidade do object de cadeia de objects de cordas Naresh , nunca irá mudar. Então, quando fazemos qualquer alteração em a object em vez de uma mudança no object de cadeia, o Naresh JVM cria um novo object que o atribui a a e, em seguida, faz a mudança nesse object.

Portanto, o conjunto de strings só é possível devido à imutabilidade de String e se String não fosse imutável, o armazenamento em cache de objects de string e sua reutilização não teriam a possibilidade, pois qualquer variável teria alterado o valor e corrompido outros.

E é por isso que o JVM é tratado de maneira muito especial e recebeu uma área de memory especial.

2. Segurança de Roscas

Um object é chamado thread-safe quando vários segmentos estão operando nele, mas nenhum deles é capaz de corromper seu estado e object manter o mesmo estado para cada thread em qualquer momento.

Como nós, um object imutável, não pode ser modificado por ninguém após sua criação, o que faz com que todo object imutável seja thread safe por padrão. Não precisamos aplicar medidas de segurança de thread, como a criação de methods sincronizados.

Então, devido a sua natureza imutável, o object string pode ser compartilhado por vários threads e, mesmo se estiver sendo manipulado por muitos threads, ele não mudará seu valor.

3. Segurança

Em cada aplicação, precisamos passar vários segredos, por exemplo, user-name \ passwords do usuário, URLs de conexão e, em geral, todas essas informações são passadas como o object string.

Agora, suponha que se String não fosse imutável por natureza, isso causaria uma séria ameaça à segurança do aplicativo, pois esses valores podem ser alterados e, se permitido, eles podem ser alterados devido a códigos escritos erroneamente ou a qualquer outra pessoa que ter access às nossas referências variables.

4. Carregamento de Classe

Como discutido em Criando objects através do Reflection em Java com o Example , podemos usar o Class.forName("class_name") para carregar uma class na memory que novamente chama outros methods para fazer isso. E até a JVM usa esses methods para carregar classs.

Mas, se você vir claramente, todos esses methods aceitam o nome da class como um object de string, de modo que as Strings são usadas no carregamento de class java e a imutabilidade fornece segurança de que a class correta está sendo carregada pelo ClassLoader .

Suponha que se String não fosse imutável e estivéssemos tentando carregar o java.lang.Object que foi alterado para org.theft.OurObject entre e agora todos os nossos objects têm um comportamento que alguém pode usar para coisas indesejadas.

5. Cache de HashCode

Se formos realizar qualquer operação relacionada a hash em qualquer object, devemos sobrescrever o hashCode() e tentar gerar um hashcode preciso usando o estado do object. Se o estado do object estiver sendo alterado, o que significa que seu hashcode também deve ser alterado.

Como String é imutável, o valor que um object de string está mantendo nunca será alterado, o que significa que seu hashcode também não será alterado, o que dá à class String uma oportunidade de armazenar em cache seu hashcode durante a criação do object.

Sim, o object String armazena em cache seu hashcode no momento da criação do object, o que o torna o grande candidato a hashing de operações relacionadas, pois o hashcode não precisa ser calculado novamente, o que nos poupa algum tempo. É por isso que o String é usado principalmente como chaves HashMap .

Leia mais sobre o Why String é imutável e final em Java .

Eu li este post porque String é imutável ou final em Java e suponho que seguir pode ser o motivo mais importante:

String é Imutável em Java porque os objects String são armazenados em cache no conjunto de Sequências . Como os literais String em cache são compartilhados entre vários clientes, há sempre um risco, em que a ação de um cliente afetaria todos os outros clientes.

String é imutável porque: –

1. Design: – O conjunto de strings só é possível porque String é imutável em java, desta forma o Java Runtime economiza muito espaço de heap java, pois diferentes variables ​​String podem se referir à mesma variável String no conjunto. Se String não fosse imutável, então a internação de String não teria sido possível porque se qualquer variável alterasse o valor, ela também teria sido refletida para outras variables.

2. Segurança: – Se o String não for imutável, isso causaria grave ameaça à segurança do aplicativo. Por exemplo, nome de usuário do database, senha são passados ​​como String para obter conexão com o database e no host de programação do soquete e detalhes da porta passados ​​como String. Como String é imutável, seu valor não pode ser alterado, caso contrário, qualquer hacker pode alterar o valor referenciado para causar problemas de segurança no aplicativo.

3. Segmento Segura: – Como String é imutável, é seguro para multithreading e uma única instância String pode ser compartilhada entre diferentes threads. Isso evita o uso de synchronization para segurança de thread, Strings são implicitamente thread-safe

4. classloader: – As strings são usadas no classloader java e a imutabilidade fornece segurança de que a class correta está sendo carregada pelo Classloader. Por exemplo, pense em uma instância em que você está tentando carregar a class java.sql.Connection, mas o valor referenciado é alterado para myhacked.Connection, que pode fazer coisas indesejadas em seu database.

5. Caching: – Como String é imutável, seu hashcode é armazenado em cache no momento da criação e não precisa ser calculado novamente. Isso o torna um ótimo candidato para a chave em um mapa e seu processamento é rápido do que outros objects-chave do HashMap. É por isso que String é usado principalmente como chaves HashMap. Acima estão algumas das razões que eu poderia pensar que mostra os benefícios da imutabilidade de String. É um ótimo recurso da class Java String e o torna especial.

Você está certo. String em java usa o conceito de literal String Pool . Quando uma string é criada e a string já existe no pool, a referência da string existente será retornada, em vez de criar um novo object e retornar sua referência. Se uma string não for imutável, a mudança da string com uma referência será levar ao valor errado para as outras referências.

Eu adicionaria mais uma coisa, já que String é imutável, é seguro para multi-threading e uma única instância de String pode ser compartilhada através de diferentes threads. Isso evita o uso de synchronization para segurança de thread, Strings são implicitamente thread safe .

A class String é FINAL que significa que você não pode criar nenhuma class para herdá-la e mudar a estrutura básica e tornar o Sting mutável.

Outra variável de instância e methods da class String que são fornecidos são tais que você não pode alterar o object String depois de criado.

O motivo pelo qual você adicionou não torna o String imutável. Isso tudo diz como o String é armazenado em heap. Também o pool de strings faz a enorme diferença no desempenho

String é dado como imutável por sistemas micro da Sun, porque string pode ser usada para armazenar como chave na coleção de mapas. StringBuffer é mutável. Essa é a razão, ele não pode ser usado como chave no object de mapa

A razão mais importante de uma cadeia ser imutável em Java é a consideração de segurança . Em seguida seria Caching .

Acredito que outras razões dadas aqui, como eficiência, concorrência, design e pool de strings, se seguem ao fato de String ser imutável. Por exemplo O conjunto de strings poderia ser criado porque String era imutável e não o contrário.

Verifique a transcrição da entrevista de Gosling aqui

De um ponto de vista estratégico, eles tendem a ser mais frequentemente livres de problemas. E geralmente há coisas que você pode fazer com imutáveis ​​que você não pode fazer com coisas mutáveis, como armazenar em cache o resultado. Se você passar uma string para um método de abertura de arquivo, ou se você passar uma string para um construtor por um label em uma interface de usuário, em algumas APIs (como em muitas APIs do Windows) você passa uma matriz de caracteres. O receptor desse object realmente tem que copiá-lo, porque eles não sabem nada sobre o tempo de vida de armazenamento dele. E eles não sabem o que está acontecendo com o object, se ele está sendo alterado sob seus pés.

Você acaba sendo quase forçado a replicar o object porque não sabe se é ou não proprietário dele. E uma das coisas boas sobre objects imutáveis ​​é que a resposta é: “Sim, claro que sim”. Porque a questão da propriedade, quem tem o direito de mudar isso, não existe.

Uma das coisas que forçou a Strings a ser imutável foi a segurança. Você tem um método de abertura de arquivos. Você passa uma String para ela. E então está fazendo todo tipo de verificação de autenticação antes de fazer a chamada do SO. Se você conseguir fazer algo que efetivamente tenha alterado o String, após a verificação de segurança e antes do sistema operacional, então, boom, você está dentro. Mas as Strings são imutáveis, então esse tipo de ataque não funciona. Esse exemplo preciso é o que realmente exigia que o Strings fosse imutável

Além das ótimas respostas, queria adicionar alguns pontos. Como Strings, Array contém uma referência ao início da matriz, portanto, se você criar duas matrizes arr1 e arr1 e arr2 algo como arr2 = arr1 isso fará com que a referência de arr2 igual a arr1 portanto, alterar o valor em uma delas resultará em alteração do outro por exemplo

 public class Main { public static void main(String[] args) { int[] a = {1, 2, 3, 4}; int[] b = a; a[0] = 8; b[1] = 7; System.out.println("A: " + a[0] + ", B: " + b[0]); System.out.println("A: " + a[1] + ", B: " + b[1]); //outputs //A: 8, B: 8 //A: 7, B: 7 } } 

Não só isso causaria erros no código como também pode (e será) explorado por um usuário mal-intencionado. Suponha que você tenha um sistema que altere a senha do administrador. O usuário deve primeiro inserir o newPassword e, em seguida, o oldPassword se o oldPassword for o mesmo que o adminPass o programa alterará a senha por adminPass = newPassword . Digamos que a nova senha tenha a mesma referência que a senha do administrador, portanto, um programador ruim pode criar uma variável temp para manter a senha do administrador antes que os usuários oldPassword dados, se oldPassword for igual a temp , alterará a senha caso contrário adminPass = temp . Alguém sabendo que poderia facilmente digitar a nova senha e nunca digitar a senha antiga e abracadabra ele tem access de administrador. Outra coisa que eu não entendi quando aprendi sobre Strings, porque a JVM não cria uma nova string para cada object e tem um lugar único na memory e você pode fazer isso usando new String("str"); A razão pela qual você não iria querer usar sempre new é porque não é eficiente em termos de memory e é mais lento na maioria dos casos, leia mais .

Se HELLO é sua String, então você não pode mudar HELLO para HILLO . Essa propriedade é chamada de propriedade de imutabilidade.

Você pode ter várias variables ​​String de ponteiro para apontar a HELLO String.

Mas se HELLO é char Array então você pode mudar HELLO para HILLO. Por exemplo,

 char[] charArr = 'HELLO'; char[1] = 'I'; //you can do this 

Responda:

As linguagens de programação possuem variables ​​de dados imutáveis ​​para que possam ser usadas como chaves no par chave, valor. Variáveis ​​de string são usadas como chaves / índices, então elas são imutáveis .

Do ponto de vista da Security , podemos usar este exemplo prático:

 DBCursor makeConnection(String IP,String PORT,String USER,String PASS,String TABLE) { // if strings were mutable IP,PORT,USER,PASS can be changed by validate function Boolean validated = validate(IP,PORT,USER,PASS); // here we are not sure if IP, PORT, USER, PASS changed or not ?? if (validated) { DBConnection conn = doConnection(IP,PORT,USER,PASS); } // rest of the code goes here .... }