Executem o código abaixo:
public class TestaStrings {
public static void main(String[] args) {
String s1 = new String ("Brasil");
String s2 = new String ("Brasil");
System.out.println(s1 == s2); // false
String s3 = "Brasil";
String s4 = "Brasil";
System.out.println(s3 == s4); // true
System.out.println(s3.hashCode());
System.out.println(s3.hashCode());
s4 = "Paraguai";
System.out.println(s3 == s4); // false
System.out.println(s4.hashCode());
}
}
No primeiro caso são criadas duas variáveis de objeto diferentes, s1 e s2, apontando para dois objetos diferentes no heap.
No segundo caso são criadas duas variáveis de objeto diferentes, s3 e s4, apontando para o mesmo objeto no heap.
Como isso acontece?
a) Quando declaramos a String s3 o Java cria o objeto do tipo String com valor "Brasil" em uma área chamada pool de Strings.
b) Como Strings são imutáveis, ao declararmos a String s4 e atribuirmos o valor "Brasil" o java procura no Pool de Strings se já existe um objeto com o valor "Brasil". Como este objeto já existe, o java irá apontar a variável s4 para o mesmo objeto que s3 aponta. Vejam os valores dos hashcodes indicando que os objetos ocupam exatamente o mesmo endereço.
d) Ao mudarmos o valor do String s4 o java irá criar outro objeto e apontar a variável para ele, uma vez que Strings são imutáveis. Vejam que o hashcode de s4 mudou.