Java Operadores de Comparação
Programas tomam decisões o tempo todo: "a nota é suficiente para passar?", "o estoque acabou?", "a senha está certa?". Cada uma dessas perguntas é uma comparação, e a resposta é sempre sim ou não: true ou false. Nesta aula você vai conhecer os seis operadores de comparação do Java e as armadilhas de comparar textos e números decimais.
- Os operadores
==,!=,>,<,>=e<=. - Que toda comparação produz um
boolean, que pode ser guardado numa variável. - O que dá para comparar: números,
chareboolean. - Por que não usar
==comStringnem comdouble. - Os erros mais comuns, como
18 <= idade < 60e=no lugar de==.
Os seis operadores
São os sinais da matemática da escola, escritos com os caracteres do teclado. A Ana tirou 7 na prova:
public class Main {
public static void main(String[] args) {
int nota = 7;
System.out.println(nota == 7);
System.out.println(nota != 7);
System.out.println(nota > 6);
System.out.println(nota < 6);
System.out.println(nota >= 7);
System.out.println(nota <= 5);
}
}
$ javac Main.java && java Main true « 7 é igual a 7 false « 7 é diferente de 7? não true false true « 7 é maior OU igual a 7 false
| Operador | Pergunta | Na matemática | Exemplo (nota = 7) |
|---|---|---|---|
== | É igual? | = | nota == 7 → true |
!= | É diferente? | ≠ | nota != 7 → false |
> | É maior? | > | nota > 6 → true |
< | É menor? | < | nota < 6 → false |
>= | É maior ou igual? | ≥ | nota >= 7 → true |
<= | É menor ou igual? | ≤ | nota <= 5 → false |
Detalhes de escrita que causam erro (todos com a mensagem real em Quando dá errado):
- Igualdade usa dois sinais:
==. Um só (=) é atribuição, assunto de Operadores de Atribuição. - Os sinais de dois caracteres são escritos juntos e na ordem certa:
>=e<=(nunca=>,=<ou= =). Dica: leia em voz alta, "maior ou igual": o>vem primeiro. !=vem do!, que em Java quer dizer "não": "não igual".
O resultado é um boolean
Uma comparação não é uma ordem, é uma pergunta, e a resposta é um valor do tipo boolean (char e boolean). Como qualquer valor, ele pode ser guardado numa variável, impresso ou usado em outra conta:
public class Main {
public static void main(String[] args) {
int idade = 17;
double altura = 1.65;
boolean maiorDeIdade = idade >= 18;
boolean podeBrincar = altura >= 1.40;
System.out.println("Maior de idade? " + maiorDeIdade);
System.out.println("Pode ir no brinquedo? " + podeBrincar);
System.out.println(5 == 5.0);
System.out.println('a' < 'b');
System.out.println('Z' < 'a');
System.out.println('A' == 65);
System.out.println(true == false);
System.out.println("Resultado: " + (3 > 2));
}
}
$ javac Main.java && java Main Maior de idade? false Pode ir no brinquedo? true true « 5 == 5.0: o int vira double e os valores são iguais true « 'a' (97) < 'b' (98) true « 'Z' (90) < 'a' (97): maiúsculas vêm antes! true « 'A' é o código 65 false Resultado: true
- boolean
- O tipo da variável: guarda
trueoufalse. - maiorDeIdade
- Um nome que soa como pergunta.
- =
- Atribuição: guarda o resultado da direita.
- idade >= 18
- A comparação, calculada primeiro:
17 >= 18éfalse.
Na última linha, os parênteses em (3 > 2) são necessários: sem eles, o Java tentaria colar "Resultado: " + 3 antes de comparar, e o código não compilaria (veja Precedência).
O que dá para comparar
| Tipos | == e != | > < >= <= | Observação |
|---|---|---|---|
Números (int, double…), misturados ou não | Sim | Sim | O menor tipo é convertido: 5 == 5.0 é true. Cuidado com double (abaixo). |
char | Sim | Sim | Compara os códigos Unicode: 'A' < 'Z' < 'a' < 'z'. |
boolean | Sim | Não | true > false não compila. |
String e outros objetos | Compila, mas engana | Não | Use equals e compareTo (abaixo). |
boolean com true
if (pago == true) funciona, mas é redundante: pago já é true ou false. Escreva if (pago). Para o contrário, if (!pago) em vez de if (pago == false). O ! está em Operadores Lógicos.
Missão: no Brasil, pode votar quem tem 16 anos ou mais. O programa diz que alguém de 16 anos não pode. Corrija o operador de comparação para mostrar Pode votar? true.
public class Main {
public static void main(String[] args) {
int idade = 16;
boolean podeVotar = idade > 16;
System.out.println("Pode votar? " + podeVotar);
}
}
public class Main {
public static void main(String[] args) {
int idade = 16;
boolean podeVotar = idade >= 16;
System.out.println("Pode votar? " + podeVotar);
}
}
A armadilha: == com String
Com tipos primitivos, == compara valores. Com objetos, como String, == compara outra coisa: se as duas variáveis apontam para o mesmo objeto na memória. Dois textos iguais podem estar em objetos diferentes:
public class Main {
public static void main(String[] args) {
String a = "Ana";
String b = "Ana";
String c = new String("Ana");
System.out.println(a == b);
System.out.println(a == c);
System.out.println(a.equals(c));
}
}
$ javac Main.java && java Main true « a e b: por acaso, o mesmo objeto false « a e c: mesmo texto, objetos diferentes! true « equals compara o TEXTO
O resultado de == depende de como a String foi criada, e textos digitados pelo usuário ou lidos de arquivos quase sempre são objetos novos. Por isso a regra é simples: para comparar textos, use equals: nome.equals("Ana"). A explicação completa, com a "prova real" e o equalsIgnoreCase, está em Strings. E < e > nem compilam com String; para ordem alfabética, existe compareTo, também em Strings.
Primitivos (int, double, char, boolean): ==. Objetos (String e tudo que começa com maiúscula): equals.
Comparar double
Como você viu em double e float, contas com decimais acumulam pequenos erros. Uma comparação com == pode falhar mesmo quando "deveria" dar certo:
public class Main {
public static void main(String[] args) {
double total = 0.1 + 0.2;
System.out.println(total == 0.3);
System.out.println(Math.abs(total - 0.3) < 1e-9);
double nada = 0.0 / 0;
System.out.println(nada == nada);
System.out.println(nada != nada);
System.out.println(Double.isNaN(nada));
System.out.println(0.1 + 0.2 > 0.3);
}
}
$ javac Main.java && java Main false « 0.30000000000000004 não é 0.3 true « com tolerância: "a diferença é menor que 0,000000001?" false « NaN não é igual nem a si mesmo true true true « 0.1 + 0.2 é (um pouquinho) MAIOR que 0.3
| Para saber se… | Não use | Use |
|---|---|---|
dois double são "iguais" | a == b | Math.abs(a - b) < 1e-9 (a tolerância depende do problema) |
um valor é NaN | x == Double.NaN (sempre false) | Double.isNaN(x) |
| um valor passou de um limite | — | >, <, >=, <= funcionam bem, exceto exatamente na fronteira |
1e-9 é notação científica: 1 × 10-9, ou 0,000000001.
Missão: confirme no JShell que 0.1 + 0.2 == 0.3 dá false. Depois teste Math.abs(0.1 + 0.2 - 0.3) < 1e-9.
0.1 + 0.2 == 0.3
Quando dá errado
18 <= idade < 60: "bad operand types for binary operator '<'"
public class Main {
public static void main(String[] args) {
int idade = 25;
System.out.println(18 <= idade < 60);
}
}
$ javac Main.java
Main.java:4: error: bad operand types for binary operator '<'
System.out.println(18 <= idade < 60);
^
first type: boolean
second type: int
1 error
O que quer dizer: na matemática, "18 ≤ idade < 60" é uma frase só. Em Java, cada operador compara dois valores, da esquerda para a direita: primeiro 18 <= idade vira true, e depois o Java tentaria true < 60. Os tipos dos dois lados aparecem no erro: first type: boolean, second type: int. Comparar um boolean com um número não faz sentido.
Como consertar: faça duas comparações e junte com && ("e"): idade >= 18 && idade < 60. O && é o assunto da próxima aula, Operadores Lógicos.
Missão: o cinema cobra inteira de quem tem de 18 a 59 anos. O programa não compila. Reescreva a comparação com duas partes ligadas por && para que ele mostre Paga meia? false.
public class Main {
public static void main(String[] args) {
int idade = 25;
boolean pagaInteira = 18 <= idade < 60;
System.out.println("Paga meia? " + !pagaInteira);
}
}
public class Main {
public static void main(String[] args) {
int idade = 25;
boolean pagaInteira = idade >= 18 && idade < 60;
System.out.println("Paga meia? " + !pagaInteira);
}
}
$ javac Main.java
Main.java:4: error: bad operand types for binary operator '=='
System.out.println(letra == "a");
^
first type: char
second type: String
1 error
O que quer dizer: letra é um char e "a", com aspas duplas, é uma String. Tipos sem relação não podem ser comparados. O mesmo erro aparece em nome == idade (String com int), em pago > false (boolean com >) e em "abacaxi" < "banana" (String com <).
Como consertar: compare valores do mesmo tipo: letra == 'a', com aspas simples. Para textos, equals e compareTo.
=>, =<, = =
$ javac Main.java
Main.java:4: error: illegal start of expression
System.out.println(x => 3);
^
1 error
$ javac Main.java
Main.java:4: error: illegal start of type
System.out.println(x =< 3);
^
1 error
O que quer dizer: o Java leu um = (atribuição) seguido de um > ou < solto, que não podem começar uma expressão. Com espaço no meio, x = = 5 também dá illegal start of expression. As mensagens não falam em "operador errado", mas o ^ aponta para o lugar.
Como consertar: >=, <= e ==, juntos, com o = sempre por último.
= no lugar de == num if: "int cannot be converted to boolean"
O que quer dizer: if (idade = 18) atribui em vez de comparar, e o resultado (um int) não serve de condição. O erro real está em Operadores de Atribuição.
Como consertar: if (idade == 18).
false com textos iguais
O que aconteceu: você usou == com String. Compila, mas compara se é o mesmo objeto, não o mesmo texto.
Como consertar: texto1.equals(texto2). Veja Strings.
Referência
| Operador | Significado | Exemplo → resultado |
|---|---|---|
a == b | Igual (primitivos) | 7 == 7 → true |
a != b | Diferente | 7 != 7 → false |
a > b | Maior | 7 > 6 → true |
a < b | Menor | 'a' < 'b' → true |
a >= b | Maior ou igual | 7 >= 7 → true |
a <= b | Menor ou igual | 7 <= 5 → false |
s1.equals(s2) | Mesmo texto (String) | "Ana".equals(nome) |
Math.abs(a - b) < tol | "Iguais" para double | Math.abs(0.1 + 0.2 - 0.3) < 1e-9 → true |
Double.isNaN(x) | x é NaN? | |
min <= x && x <= max | Está entre dois valores | Veja Operadores Lógicos |
Exercícios
1. Diferente
Complete com o operador "diferente de":
2. Aprovação
Aprova quem tira 6 ou mais. Complete:
3. Textos
Complete para comparar o texto de nome com "Ana":
4. Qual o tipo do resultado de idade > 18?
5. O que System.out.println('Z' < 'a'); mostra?
6. Por que 18 <= idade < 60 não compila?
7. Qual o jeito certo de saber se o double total "vale" 0.3?
Resumo
- Seis operadores:
==,!=,>,<,>=,<=. Igualdade tem dois sinais; os compostos têm o=por último. - Toda comparação dá um
boolean, que pode ser guardado:boolean aprovado = nota >= 6;. - Números se comparam entre si (
5 == 5.0étrue);charcompara códigos Unicode;booleansó com==e!=. String: useequals, não==.double: compare com tolerância;NaNse testa comDouble.isNaN.- "Entre dois valores" são duas comparações:
x >= 18 && x < 60.