2

String (==) ou equals

#Java
Eduardo Albuquerque
Eduardo Albuquerque

Olá pessoa, nesse artigo irei falar um pouco de uma dúvida recorrente entre desenvolvedores JAVA.


Quando usar a dupla igualdade ( == ) ou o método equals.


Então bora lá.


O primeira coisa, é entendermos que String NÃO é um tipo primitivo de dados como byte, short, int, long, float, double, char e boolean e sim um objeto.


String é a instância da classe java.lang.String, logo ele deverá ser declarada e instanciada.


Porém a ideia desse artigo não será nos aprofundarmos nos métodos das classe String, iremos apenas tentar passar para vocês por que as vezes utilizamos a dupla igualdade (==) e funciona e outras vezes temos que utilizar o equals para que o resultado seja como esperado.


Existe uma diferença entre usar String Literals e String Object, e iremos entender agora:


String Literals tem a seguinte sintaxe :

String <nome_da_variavel> = "algo ou nada"


Sempre que tivermos uma variável do tipo String recebendo uma cadeia de caracteres entre aspas duplas, teremos então uma String Literals. obs: pode ser vazia String a = ""


Dessa forma a JVM armazena cada cópia da String literal no String pool em um processo chamado de interning, com disso a String literals sempre irá se referenciar a mesma instância da classe String.


Quando precisamos buscar uma String Literals a JVM verifica se já existe no String Pool aquele valor, caso não exista, ela cria um novo objeto que poderá ser utilizado em algum momento futuro. abaixo iremos exemplificar para facilitar o entendimento do que foi falado até o momento.


String a = "123";
String b = "123";
System.out.print( a == b); //true

String s1 = "java";
String s2 = "java";
System.out.print( a == b); //true


Notem que criei as variáveis a e b do tipo String e quando consultamos/comparamos utilizando a dupla igualdade o retorno é verdadeiro(true). "123" é igual a "123" e a mesma coisa acontece para as variáveis s1 e s2. Isso acontece por que ambas variáveis a, b, s1 e s2 foram armazenadas em uma mesma instância


A String Literal sempre será referenciada a mesma instância da classe String;


Já quando utilizamos a instrução new, estamos obtendo um novo objeto String e dessa maneira apontando para espaços diferente na memória heap.

String a = "123";
String b = new String("123"); // new instance
System.out.print(a == b); //false

String s1 = "java";
String s2 = new String("java"); // new instance
System.out.print(s1 == s2); //false


Analisando o código acima iremos notar que o retorno agora foi falso(false). na linha 10 utilizamos a String Literals para colocar dentro da variável a o valor "123" e dentro da variável b o mesmo valor "123", porém, na linha 11 utilizamos a instrução new para criar uma nova instância da classe String, fazendo com que a JVM armazene em outra parte da memória heap e nao no String Pool onde já existia o mesmo valor "123". O mesmo acontece nas linhas 14 e 15 do trecho de código acima, notem que mesmo utilizando a instrução new para as duas variáveis s1 e s2 e colocando o mesmo valor, o retorno será falso(false), exatamente por que dessa forma a JVM irá armazenar cada variável em locais diferentes da memória heap.


Agora que sabemos que o duplo igual (==) irá funcionar perfeitamente em String Literals, e não irá funcionar quando formos comparar as variáveis instanciadas em lugares diferentes da memória. Para fazer funcionar a comparação apresentada no código acima, vamos para mais um trecho de código:

String a = "123";
String b = new String("123") //new instance
System.out.print(a.equals(b)); //true

String s1 = "java";
String s2 = new String("java") //new instance
System.out.print(s1.equals(s2)); //true
Quando queremos comparar instâncias distintas da classe String utilizaremos o método da classe equals. vejam pela figura acima que agora o retorno é verdadeiro(true), tanto comparando a variável a (String Literals) com b (Object String) como no segundo exemplo nas variáveis s1 (Object String) com s2 (Object String) ambas retornam verdadeiras.


Bom, ainda não paramos por aqui, antes de finalizar gostaria de mostrar que podemos internar (intern) ou seja, transferir uma referência que está na memória heap para a String Pool de maneira simples, basta utilizar o método .intern no objeto que queremos internar, vamos para o exemplo.

String a = "123";
String b = new String("123"); // new instance
System.out.print(a == b.intern()); // true

String s1 = "java";
String s2 = new String("java"); // new instance
System.out.print(s1 == s2.intern()); // true

Estou utilizando sempre o mesmo exemplo para facilitar seu entendimento, nesse novo cenário podemos perceber que agora na linha 12 temos uma comparação utilizando o duplo igual ( == ) entre uma String literals a e um Object String b e mesmo assim o retorno foi verdadeiro (true), porém, isso só foi possível porque a variável b que foi instanciada a princípio em outra localização da memória heap (utilizando a instrução new - linha 11) foi forçada a ir para a String Pool, permitindo dessa forma ser comparada com a variável a que já se encontrava na String pool. O mesmo acontece com as variáveis s1 e s2, ambas fora para String Pool para serem comparadas com o duplo igual ( == ).


Bom pessoal, espero de coração ter contribuído de alguma forma para o seu crescimento como desenvolvedor java.


obs: escrevi esse artigo também no meu linkedin, quem quiser pode me acompanhar por lá!

https://www.linkedin.com/in/webdevbrasil/


1
40

Comentários (1)

0
N

Neydson Medeiros

13/12/2020 09:15

Obrigado companheiro. Ótimo artigo.

Dev JAVA

Brasil