Solucionado (ver solução)
Solucionado
(ver solução)
3
respostas

String literal vs new String("");

Resolvi testar uma coisa com a classe String... Fiz o seguinte teste:

String a  = new String("Test string");
String b = "Test string";
System.out.println(b == a) // false

String x =  "New test";
String y = "New test";
System.out.println(x == y) // true

Pelo o que eu entendi, quando criamos uma String de forma literal, por baixo dos panos ele cria uma referência á uma String com otimizações. E utilizando o operador new ele também cria uma referência para uma String porém sem otimizações.

Porque quando crio Strings de forma literal e faço uma comparação entre elas, ele compara o valor delas e não a referência? Quando eu crio uma String usando o new e comparo com uma String literal, ele me retorna false. Por que isso acontece?

3 respostas
solução!

Bom, objetos do tipo String em Java são Imutáveis, ou seja, não é possivel alterar um objeto do tipo String.

exemplo:

private String name = "nome"; 
name = "myname";

o Objeto String com valor "nome" contínua existindo na memória após a execução da linha abaixo de sua declaração, e uma nova referencia de Objeto do tipo String é retornada a variavel 'name', que agora vai referenciar o "myname". É por isso que todos os metodos de manipulação de Strings retornam uma String, pois eles nao alteram o objeto que chamou o metodo, mas sim devolvem uma nova String,

Essa caracteristica das Strings possibilita uma abordagem chamada "String Pool", que permite à JVM isolar objetos que tem o mesmo valor, não repetindo nenhum deles, ou seja, se voce criar (sem o 'new')1000 Strings com o mesmo conteudo, na verdade todas suas variaveis vão apontar para 1 único objeto, fazendo com que se consuma menos memória da aplicação .

Acontece que ao criar uma String usando a palavra 'new', você OBRIGA a JVM a criar um novo objeto, o qual não fará parte do String Pool, então ele não vai consultar o String Pool e verificar se aquela String existe ou não, ele simplesmente vai criar uma nova. Isso pode ser bom ou ruim, já que na hora de criar sua String a JVM nao vai buscar por Strings que tenham o mesmo valor, o que poderia acabar tendo um maior custo de processamento, mas ao mesmo tempo voce não estará reutilizando suas Strings e terá um maior consumo de memória. . Existe um metodo na Classe String para "jogar" uma String para o String Pool.


        String name = new String("nome");
        String nameOnStringPool = "nome";
        System.out.println(name == nameOnStringPool); // false, como você já viu

        String name = new String("nome");
        String nameOnStringPool = "nome";
        System.out.println(name.intern() == nameOnStringPool); // true

Oi Leonardo, tudo bem?

Antes de mais nada, acho válido entendermos como funciona essas otimizações por baixo dos panos para que a explicação fique mais clara.

Primeiro, quando declaramos uma String Object, ou seja, uma string criada a partir do operador new(), como por exemplo String obj = new String("Java"), estamos criando um novo objeto String num lugar chamado heap memory, que é basicamente, o lugar onde a JVM deixa guardado todos os objetos que vão sendo criados ao decorrer do nosso programa.

Já quando declaramos uma String Literal, ou seja, uma string com sintaxe literal como String literal = "Java", antes de mais nada é feita uma busca pela string declarada "Java" num lugar onde strings são armazenadas chamada string pool - que também fica dentro da heap memory - então, toda vez que uma string literal é criada, a JVM checa se essa string já existe na string pool. Caso ela exista, é retornado a referência para a string, mas caso ela não exista, uma nova string object é inicializada e adicionada na string pool para que futuramente, se outra string literal for criada, não seja necessário inicializar um novo objeto e possamos pegá-la diretamente da string pool.

Aqui temos uma imagem que ilustra isso:

Imgur

Como podemos ver, se declararmos duas Strings literais a e b e formos compará-las com ==, estamos comparando dois valores que referenciam o mesmo lugar - ou melhor, a mesma string - por isso é retornado true! Diferente da String object c que foi criada no heap memory e continua apontando para lá sem nunca ter checado a string pool.

Só respondendo brevemente a sua primeira pergunta, a comparação ainda é feita através das referências, o que acontece é que na segunda vez que você declarou a string literal "New test", a JVM simplesmente foi até a string pool, achou a string "New test" que foi declarada anteriormente e passou a apontar para essa mesma referência.

Espero ter ajudado, qualquer dúvida estamos à sua disposição!

Bons estudos!!

Entendi perfeitamente Thiago. Muito obrigado pela sua explicação, foi muito esclarecedora. Então por isso é melhor criar uma String literal, porque se ela não existe na String Pool, ele cria a referência e coloca ela dentro. Agora com o String Object, ele nunca irá para o String Pool e consequentemente irá criar sempre uma nova referência para a string que pode já existir.