Um operador relacional testa o relacionamento entre dois valores. Um exemplo é o operador <= utilizado no teste
if (amount <= balance)
Java tem seis operadores relacionais:
Java Notação matemática Descrição
> > Maior que
>= ≥ Maior que ou igual a
< < Menor que
<= ≤ Menor que ou igual a
== = Igual
!= ≠ Diferente de
Como você pode ver, somente dois operadores relacionais (> e <) se parecem com aque- les da notação matemática que já conhecemos. Teclados de computador não têm teclas para ≥, ≤ ou ≠, mas os operadores >=, <= e != são fáceis de lembrar porque são seme- lhantes.
Inicialmente, o operador == é confuso para a maioria dos iniciantes em Java. Em Java, o símbolo = já tem um signifi cado, a saber, atribuição. O operador == denota teste de igualdade:
Operadores relacionais comparam valores. O operador == testa a igualdade.
a = 5; // Atribui 5 a a
if (a == 5) . . . // Testa se a é igual a 5
Você precisará lembrar de utilizar == para teste de igualdade e = para atribuição.
5.2.2 Comparando números de ponto fl utuante
Tenha cuidado ao comparar números de ponto fl utuante para que possa tratar erros de arredondamento. Por exemplo, o código a seguir multiplica a raiz quadrada de 2 por ela mesma e então subtrai 2.
double r = Math.sqrt(2); double d = r * r - 2; if (d == 0)
System.out.println("sqrt(2) squared minus 2 is 0"); else
System.out.println(
"sqrt(2) squared minus 2 is not 0 but " + d);
Embora as leis da matemática digam que – 2é igual a 0, esse fragmento de pro- grama imprime:
sqrt(2) squared minus 2 is not 0 but 4.440892098500626E-16
Infelizmente, esses erros de arredondamento são inevitáveis. Simplesmente não faz sen- tido, na maioria das vezes, comparar números de ponto fl utuante de uma maneira exata. Em vez disso, teste se eles são sufi cientemente próximos.
Para testar se um número x é próximo de zero, você pode testar se o valor absoluto | x | (isto é, o número com seu sinal removido) é menor que um número de limiar bem pequeno. O valor desse limiar costuma ser chamado de ε (a letra grega épsilon). É comum confi gurar ε como 10–14 ao testar números double.
Da mesma forma, você pode testar se dois números são aproxi- madamente iguais verifi cando se a diferença é próxima de 0.
Em Java, programamos o teste assim: fi nal double EPSILON = 1E-14; if (Math.abs(x - y) <= EPSILON) // x é aproximadamente igual a y
5.2.3 Comparando
stringsPara testar se duas strings são iguais, você deve utilizar o método equals: if (string1.equals(string2)) . . .
Não utilize o operador == para comparar strings. A expressão if (string1 == string2) // Não é útil
tem um signifi cado diferente. Ele testa se as duas variáveis alfanu- méricas referenciam o mesmo objeto string. Podemos ter strings
Ao comparar números de ponto fl utuante, não teste a igualdade. Em vez disso, verifi que se eles são sufi cientemente próximos.
Não utilize o operador ==
para comparar strings. Em vez disso, utilize o método
com conteúdos idênticos armazenados em objetos diferentes, portanto esse teste nunca faz sentido na programação real; veja o Erro comum 5.1.
Em Java, a distinção entre maiúsculas e minúsculas é importante. Por exemplo, "Har- ry" e "HARRY" não são strings idênticas. Para ignorar a distinção entre maiúsculas e mi- núsculas, utilize o método equalsIgnoreCase:
if (string1.equalsIgnoreCase(string2)) . . .
Se duas strings não forem idênticas, ainda será recomendável en- tender o relacionamento entre elas. O método compareTo compara strings na ordem do dicionário. Se
string1.compareTo(string2) < 0
a string string1 vem antes da string string2 no dicionário. Por exemplo, este é o caso se string1 for "Harry" e string2 for "Hello". Se
string1.compareTo(string2) > 0
string1 vem depois de string2 na ordem do dicionário. Por fi m, se string1.compareTo(string2) == 0
então string1 e string2 são iguais.
Na verdade, o ordenamento do tipo “dicionário” utilizado em Java é um pouco dife- rente daquele de um dicionário normal. Java diferencia letras maiúsculas de minúsculas e classifi ca caracteres colocando primeiro os números, em seguida os caracteres em letras maiúsculas e então os caracteres em letras minúsculas. Por exemplo, 1 vem antes de B, que vem antes de a. O caractere de espaço em branco vem antes de todos os outros ca- racteres.
Vamos investigar o processo de comparação bem de perto. Quando Java compara duas strings, as letras correspondentes são comparadas até uma das strings terminar ou até a primeira diferença ser encontrada. Se uma das strings terminar, a string mais lon- ga será considerada a última. Se uma não-correspondência de caracteres for localizada, os caracteres são comparados para determinar qual string vem depois na seqüência do dicionário. Esse processo é chamado comparação lexicográfi ca. Por exemplo, vamos comparar "car" a "cargo". As três primeiras letras correspondem e alcançamos o fi m da primeira string. Portanto "car" vem antes de "cargo" na ordenação lexicográfi ca. Agora compare "cathode" com "cargo". As duas primeiras letras correspondem. Na terceira posição de caractere, t vem depois de r, assim a string "cathode" vem depois de "cargo" na ordenação lexicográfi ca. (Veja Figura 3.)
O método compareTo
compara strings na ordem do dicionário.
Figura 3
Comparação lexicográfi ca.
c a r g o c a t h o d As letras correspondem e r vem antes de t
Utilizando == para comparar strings
É um erro extremamente comum em Java escrever == quando o objetivo é usar equals. Isso é particularmente verdadeiro para strings. Se você escrever:
if (nickname == "Rob")
o teste então só será bem-sucedido se a variável nickname referenciar exatamente o mes- mo objeto string que a constante string "Rob". Por efi ciência, Java cria apenas um objeto string para cada constante string. Portanto, o teste a seguir passará:
String nickname = "Rob"; . . .
if (nickname == "Rob") // O teste é verdadeiro
Mas se a string com as letras R o b for montada de alguma outra maneira, o teste falhará:
String name = "Robert";
String nickname = name.substring(0, 3); . . .
if (nickname == "Rob") // O teste é falso
Essa é uma situação particularmente afl itiva: às vezes o código errado fará a coisa certa, outras vezes a coisa errada. Como objetos string sempre são construídos pelo compila- dor, nunca nos preocupamos se dois objetos string são compartilhados. Você deve lem- brar de nunca utilizar == para comparar strings. Sempre utilize equals ou compareTo
para comparar strings.
E
RROCOMUM5.1
5.2.4 Comparando objetos
Se comparar duas referências de objeto com o operador ==, você testará se essas referên- cias referenciam o mesmo objeto. Eis um exemplo:
Rectangle box1 = new Rectangle(5, 10, 20, 30); Rectangle box2 = box1;
Rectangle box3 = new Rectangle(5, 10, 20, 30); A comparação
box1 == box2
é true. Ambas as variáveis de objeto referenciam o mesmo objeto. Mas a comparação box1 == box3
é false. As duas variáveis de objeto referenciam objetos diferentes (ver a Figura 4). Não importa se os objetos tenham conteúdo idêntico.
Você pode utilizar o método equals para testar se dois retân- gulos têm o mesmo conteúdo, isto é, se eles têm o mesmo canto superior esquerdo, a mesma largura e a mesma altura. Por exem- plo, o teste
box1.equals(box3) é verdadeiro.
O operador == testa se duas referências de objeto são idênticas. Para comparar o conteúdo de objetos, você precisa utilizar o método
Entretanto, você deve ter cuidado ao utilizar o método equals. Ele só funciona corre- tamente se os implementadores da classe o defi nirem. A classe Rectangle tem um método equals adequado para comparar retângulos.
Nas suas próprias classes, você precisa fornecer um método equals apropriado. Você aprenderá a fazer isso no Capítulo 10. Até lá, você não deve utilizar o método equals para comparar objetos das suas próprias classes.
5.2.5 Testando
nullUma referência a objeto pode ter o valor especial null se ela não referenciar nenhum objeto. É comum utilizar o valor null para in- dicar que um valor nunca foi confi gurado. Por exemplo,
String middleInitial = null; // Não confi gurado
if ( . . . )
middleInitial = middleName.substring(0, 1);
Utilize o operador == (e não equals) para testar se uma referência a objeto é uma referên- cia null:
if (middleInitial == null)
System.out.println(fi rstName + " " + lastName); else
System.out.println(fi rstName + " " + middleInitial + ". " + lastName); Observe que a referência null não é a mesma coisa que a string vazia "". A string vazia é uma string válida de comprimento 0, enquanto um null indica que uma variável do tipo string não referencia absolutamente nenhuma string.
A referência null não referencia nenhum objeto.
box1 = box2 = x = Rectangle y = width = height = 5 10 20 30 30 box3 = x = Rectangle y = width = height = 5 10 20 30 30
AUTOVERIFICAÇÃODAAPRENDIZAGEM
3. Qual é o valor de s.length() se s for
a. a string vazia ""?
b. a string " " contendo um espaço?
c. null?
4. Quais comparações a seguir são sintaticamente incorretas? Quais delas são sin- taticamente corretas, mas logicamente questionáveis?
String a = "1"; String b = "one"; double x = 1; double y = 3 * (1.0 / 3); a. a == "1" b. a == null c. a.equals("") d. a == b e. a == x f. x == y g. x - y == null h. x.equals(y)
Evite condições com efeitos colaterais
Em Java, é válido aninhar atribuições dentro de condições de teste:
if ((d = b * b - 4 * a * c) >= 0) r = Math.sqrt(d);
É válido utilizar o operador de decremento dentro de outras expressões:
if (n–– > 0) . . .
Esses dois usos são práticas de programação ruins, porque misturam um teste com uma outra atividade. A outra atividade (confi gurar a variável d, decrementando n) é chamada de efeito colateral do teste.
Como veremos no Tópico Avançado 6.2, condições com efeitos colaterais podem ser úteis ocasionalmente para simplifi car laços; em comandos if elas devem ser evi- tadas sempre.