1. Comparações

Os programadores precisam comparar diferentes variáveis ​​umas com as outras o tempo todo. Mas, como você já viu, nem tudo é tão simples.

Os números inteiros são muito fáceis de comparar — basta usar ==e pronto. Para comparar números reais , você deve comparar sua diferença (ou melhor, o valor absoluto da diferença) com algum número muito pequeno.

Comparar strings é ainda mais difícil. Acima de tudo, isso ocorre porque strings são objetos. Além do mais, os programadores geralmente desejam que a comparação de strings seja um pouco diferente, dependendo da situação.


2. Como as strings são organizadas na memória

Como você já viu, as strings são armazenadas na memória de maneira diferente dos números inteiros e reais:

Como as strings são organizadas na memória

Dois blocos de memória são usados ​​para armazenar strings: um bloco armazena o próprio texto (seu tamanho depende do tamanho do texto) enquanto o segundo bloco (4 bytes) armazena o endereço do primeiro bloco.

Embora um programador experiente diria algo como "a String strvariável armazena uma referência a um Stringobjeto.


3. Atribuindo referências a uma string

Os benefícios dessa abordagem tornam-se aparentes quando você precisa atribuir uma variável de string a outra variável de string. Exemplo:

String text = "This is a very important message";
String message = text;

E aqui está o que a memória conterá como resultado:

Atribuindo referências a uma string

Após esse tipo de operação de atribuição, o Stringobjeto permanece onde estava e apenas seu endereço (uma referência ao objeto) é copiado para a messagevariável.


4. Trabalhando com referências e objetos

Mas se você decidir converter uma string para maiúsculas (letras maiúsculas), a máquina Java faz tudo certo: você vai acabar com dois Stringobjetos, e as variáveis text​​e messagevão armazenar referências, cada uma para seu próprio objeto.

Exemplo:

String text = "This is a very important message";
String message = text.toUpperCase(); 

E aqui está o que a memória conterá como resultado:

Trabalhando com referências e objetos

Observe que o toUpperCase()método não altera a string em que é chamado. Em vez disso, ele cria uma nova string (novo objeto) e retorna uma referência a ela.

Que tal um exemplo ainda mais interessante. Digamos que você decida passar uma string para um Scannerobjeto (para que ele leia os valores da string).

Exemplo:

String text = "10 20 40 80";
Scanner console = new Scanner(text);
int a = console.nextInt();
int b = console.nextInt();

Você pode aprender mais sobre como a Scannerclasse funciona aqui .

É assim que tudo ficará armazenado na memória:

Trabalhando com referências e objetos.  classe do scanner

Nesse caso, um único Stringobjeto permanece na memória exatamente como estava — apenas as referências a ele são passadas e armazenadas em variáveis.


5. Comparando referências a Stringobjetos

E, finalmente, chegamos à parte divertida: comparação de strings.

Existem dois operadores que você pode usar para comparar variáveis ​​de string: ==(igual) e !=(diferente). Você não pode usar os operadores "maior que", "menor que" ou "maior que ou igual a" — o compilador não permitirá isso.

Mas há uma nuance interessante aqui: o que realmente é armazenado em variáveis ​​de string? Isso mesmo: endereços (referências) a objetos. E são esses endereços que serão comparados:

String text = "Hi";
String message = text;
String s1 = text.toUpperCase();
String s2 = text.toUpperCase(); 

Aqui está o que ficará na memória:

Comparando referências a objetos String

As variáveis message​​e textreferem-se (armazenam o endereço) ao mesmo objeto. Mas as variáveis s1​​e s2armazenam referências a objetos que são muito semelhantes, mas distintos.

E se você comparar essas 4 variáveis ​​no código, obterá o seguinte resultado:

Código Saída do console
String text = "Hi";
String message = text;
String s1 = text.toUpperCase();
String s2 = text.toUpperCase();
System.out.println(text == message);
System.out.println(text == s1);
System.out.println(s1 == s2); 


true  // The addresses are equal
false // The addresses are different
false // The addresses are different