Java Expressões Booleanas

Todo programa toma decisões: "a aluna foi aprovada?", "a senha está certa?", "é fim de semana?". Antes de decidir, o programa precisa perguntar, e a resposta é sempre true (verdadeiro) ou false (falso). Uma pergunta assim, escrita em Java, se chama expressão booleana. Esta aula abre a seção "Decisões": tudo o que vem depois (if, ternário, switch) depende dela.

Você vai aprender
  • O que é uma expressão booleana e onde ela aparece.
  • Como guardar a resposta numa variável boolean com um nome que se lê como uma pergunta.
  • Como combinar perguntas com && (e), || (ou) e ! (não), incluindo faixas como "entre 0 e 10".
  • Como a ordem das perguntas evita uma NullPointerException (curto-circuito).
  • Como transformar o texto "true" em boolean com Boolean.parseBoolean.
  • Os erros que o javac mostra quando a expressão não é booleana.

A ideia: perguntas de sim ou não

Pense num formulário com caixinhas de marcar: "Maior de 18 anos? ☐", "Possui carteira de motorista? ☐". Cada caixinha só tem dois estados: marcada ou não. Em Java, cada caixinha é um valor boolean, e a pergunta que decide se ela fica marcada é uma expressão booleana.

O nome vem de George Boole, matemático inglês do século XIX que criou a "álgebra" do verdadeiro e falso. Você conheceu o tipo boolean em char e boolean, e os operadores que fazem as perguntas em Operadores de Comparação e Operadores Lógicos. Aqui vamos juntar tudo para escrever perguntas reais.


Perguntas que viram true ou false

Qualquer comparação é uma expressão booleana. O Java calcula a resposta, e você pode guardá-la numa variável boolean:

public class Main {
    public static void main(String[] args) {
        int idade = 17;
        double nota = 8.5;
        String cidade = "Recife";
        boolean maiorDeIdade = idade >= 18;
        boolean aprovada = nota >= 7.0;
        boolean ehRecife = cidade.equals("Recife");
        System.out.println(maiorDeIdade);
        System.out.println(aprovada);
        System.out.println(ehRecife);
        System.out.println(idade == 17);
        System.out.println(10 > 3);
    }
}
$ java Main.java
false    « 17 >= 18? não
true     « 8.5 >= 7.0? sim
true     « a cidade é "Recife"? sim
true     « a pergunta pode ir direto no println
true
boolean maiorDeIdade
Uma variável que guarda true ou false.
=
Atribuição: "guarde aqui o resultado da pergunta".
idade >= 18
A pergunta (a expressão booleana): "a idade é maior ou igual a 18?". O Java a calcula na hora, com o valor que idade tem naquele momento.
cidade.equals("Recife")
Métodos também podem ser perguntas. Todo método que devolve boolean (equals, isEmpty, contains, startsWith…) serve como expressão booleana. Lembre que Strings se comparam com equals, não com == (veja Strings).
Tipo de perguntaExemplo
Comparação de númerosidade >= 18, nota == 10, saldo < 0, x != 0
Comparação de textosnome.equals("Ana"), resposta.equalsIgnoreCase("sim")
Método que devolve booleantexto.isBlank(), email.contains("@"), Character.isDigit(c)
Uma variável booleanaprovada
Os valores literaistrue, false
Combinaçõesidade >= 18 && temCarteira

Dê nomes que se leem como perguntas

Uma variável boolean bem nomeada torna o código quase uma frase em português. Bons padrões: ehMaior, estaAprovada, temDesconto, podeVotar, fimDeSemana. Em inglês, o costume é isActive, hasDiscount, canVote. Evite nomes vagos como flag, teste ou b: daqui a um mês, ninguém vai saber o que true quer dizer ali.


Combinar perguntas: &&, || e !

Perguntas da vida real raramente são simples. "Pode dirigir?" depende da idade e da carteira. "É fim de semana?" é sábado ou domingo. Os operadores lógicos juntam perguntas:

OperadorLê-seÉ true quando…
a && b"a e b"as duas são verdadeiras
a || b"a ou b"pelo menos uma é verdadeira
!a"não a"a é falsa (inverte)
public class Main {
    public static void main(String[] args) {
        int idade = 20;
        boolean temCarteira = false;
        boolean podeDirigir = idade >= 18 && temCarteira;
        System.out.println("Pode dirigir? " + podeDirigir);

        String dia = "sábado";
        boolean fimDeSemana = dia.equals("sábado") || dia.equals("domingo");
        System.out.println("Fim de semana? " + fimDeSemana);

        double nota = 11.0;
        boolean notaValida = nota >= 0 && nota <= 10;
        System.out.println("Nota válida? " + notaValida);

        boolean chovendo = true;
        boolean levaGuardaChuva = chovendo;
        boolean vaiAPraia = !chovendo;
        System.out.println(levaGuardaChuva + " " + vaiAPraia);
    }
}
$ java Main.java
Pode dirigir? false      « tem idade, mas não tem carteira: o && exige as duas
Fim de semana? true      « é sábado: basta uma para o || dar true
Nota válida? false       « 11 passa de 10
true false               « ! inverte: chovendo → não vai à praia

Faixas: "entre 0 e 10"

Na matemática escrevemos 0 ≤ nota ≤ 10. Em Java, isso não funciona (veja "Quando dá errado"): é preciso fazer duas perguntas e juntar com &&: nota >= 0 && nota <= 10. Leia em voz alta: "nota maior ou igual a zero e nota menor ou igual a dez".

O contrário, "fora da faixa", usa ||: nota < 0 || nota > 10 ("menor que zero ou maior que dez"). Uma nota não pode ser as duas coisas ao mesmo tempo, então nota < 0 && nota > 10 seria sempre false, um erro de lógica comum.

Inverter uma combinação

Quando você coloca um ! na frente de uma combinação, o && vira || e vice-versa (as "leis de De Morgan"):

public class Main {
    public static void main(String[] args) {
        boolean a = true;
        boolean b = false;
        System.out.println(!(a && b));
        System.out.println(!a || !b);
        System.out.println(!(a || b));
        System.out.println(!a && !b);
        System.out.println(a ^ b);
        System.out.println(a != b);
        System.out.println(a == b);
    }
}
$ java Main.java
true     « !(a && b) …
true     « … é o mesmo que !a || !b
false    « !(a || b) …
false    « … é o mesmo que !a && !b
true     « ^ (ou exclusivo): true quando são DIFERENTES
true     « != entre booleanos faz o mesmo que ^
false

Exemplo do dia a dia: "não é (sábado ou domingo)" é o mesmo que "não é sábado e não é domingo", ou seja, dia útil. O ^ (ou exclusivo, "um ou outro, mas não os dois") é raro; a != b diz a mesma coisa de um jeito mais claro.

Missão: no cinema, tem meia-entrada quem tem menos de 18 anos, ou 60 ou mais, ou é estudante. Complete a expressão de meia usando ||. Com idade = 65, a saída deve ser Meia-entrada: true. Depois teste com outras idades.

public class Main {
    public static void main(String[] args) {
        int idade = 65;
        boolean estudante = false;
        boolean meia = false; // troque false pela expressão
        System.out.println("Meia-entrada: " + meia);
    }
}
public class Main {
    public static void main(String[] args) {
        int idade = 65;
        boolean estudante = false;
        boolean meia = idade < 18 || idade >= 60 || estudante;
        System.out.println("Meia-entrada: " + meia);
    }
}

A ordem importa: curto-circuito

O && e o || são "preguiçosos": avaliam da esquerda para a direita e param assim que a resposta está decidida. Num &&, se a primeira pergunta é false, o resultado já é false, e a segunda nem é feita. Num ||, se a primeira é true, pronto. Isso se chama avaliação em curto-circuito, e é uma proteção valiosa:

public class Main {
    public static void main(String[] args) {
        String nome = null;
        boolean temNome = nome != null && nome.length() > 0;
        System.out.println(temNome);
        boolean quebra = nome.length() > 0 && nome != null;
        System.out.println(quebra);
    }
}
$ java Main.java
false
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()" because "<local1>" is null
	at Main.main(Main.java:6)

As duas linhas fazem as mesmas perguntas, em ordem diferente:

  • Linha 4: nome != null é false, e o && para ali. O nome.length() nunca roda. Resultado: false, sem erro.
  • Linha 6: nome.length() roda primeiro, com nome valendo null, e derruba o programa (a NullPointerException que você conheceu em Strings).

Regra: coloque primeiro a pergunta que protege ("existe?", "não é zero?") e depois a que depende dela. Outro exemplo clássico: divisor != 0 && total / divisor > 5.


Validar com várias perguntas

Quando a condição fica grande, quebre em variáveis com nomes claros, e junte no fim. Fica muito mais fácil de ler e de achar erros:

public class Main {
    public static void main(String[] args) {
        String email = "ana@exemplo.com";
        String senha = "java2026";
        boolean emailOk = email.contains("@") && email.endsWith(".com");
        boolean senhaLonga = senha.length() >= 8;
        boolean temDigito = Character.isDigit(senha.charAt(senha.length() - 1));
        boolean cadastroOk = emailOk && senhaLonga && temDigito;
        System.out.println("E-mail ok: " + emailOk);
        System.out.println("Senha longa: " + senhaLonga);
        System.out.println("Termina com dígito: " + temDigito);
        System.out.println("Cadastro ok: " + cadastroOk);
    }
}
$ java Main.java
E-mail ok: true
Senha longa: true
Termina com dígito: true
Cadastro ok: true

Character.isDigit(c) pergunta "este caractere é um dígito?" (veja char e boolean); senha.charAt(senha.length() - 1) é o último caractere (veja Métodos de String). Compare com a versão "tudo numa linha só": email.contains("@") && email.endsWith(".com") && senha.length() >= 8 && Character.isDigit(senha.charAt(senha.length() - 1)). Funciona, mas qual parte falhou quando dá false?


Usar um boolean numa decisão

O lugar natural de uma expressão booleana é a condição de um if (assunto da próxima aula). Um detalhe de estilo: como a variável já é true ou false, não precisa compará-la com true:

public class Main {
    public static void main(String[] args) {
        boolean aprovado = true;
        if (aprovado == true) {
            System.out.println("Parabéns!");
        }
        if (aprovado) {
            System.out.println("Parabéns de novo!");
        }
        if (!aprovado) {
            System.out.println("Não aparece");
        }
    }
}
$ java Main.java
Parabéns!
Parabéns de novo!

if (aprovado == true) e if (aprovado) fazem o mesmo, mas a segunda se lê como português: "se aprovado". Para o contrário, if (!aprovado): "se não aprovado", em vez de aprovado == false.


Texto para boolean: Boolean.parseBoolean

Às vezes a resposta chega como texto: de um arquivo de configuração, de um argumento da linha de comando, do teclado. Boolean.parseBoolean(texto) ("analisar como booleano") transforma em boolean:

public class Main {
    public static void main(String[] args) {
        System.out.println(Boolean.parseBoolean("true"));
        System.out.println(Boolean.parseBoolean("TRUE"));
        System.out.println(Boolean.parseBoolean("True"));
        System.out.println(Boolean.parseBoolean("sim"));
        System.out.println(Boolean.parseBoolean("yes"));
        System.out.println(Boolean.parseBoolean(" true"));
        System.out.println(Boolean.parseBoolean(null));
        boolean ativo = true;
        String texto = String.valueOf(ativo);
        System.out.println(texto + " tem " + texto.length() + " letras");
        System.out.println(Boolean.TRUE + " " + Boolean.FALSE);
    }
}
$ java Main.java
true      « "true"
true      « maiúsculas não importam
true
false     « "sim" não é reconhecido
false     « nem "yes"
false     « nem com espaço na frente
false     « null também dá false, sem erro
true tem 4 letras      « o caminho contrário: boolean para texto
true false

A regra é simples e rígida: só o texto true (em qualquer combinação de maiúsculas) vira true; todo o resto vira false, sem erro nenhum. Isso é perigoso: um "ture" digitado errado vira false calado. Se o texto vem de uma pessoa, limpe-o antes (texto.strip()) e, se quiser aceitar "sim", compare você mesmo: resposta.strip().equalsIgnoreCase("sim").

Boolean, com B maiúsculo, é a classe "embrulho" (wrapper) do tipo boolean; ela guarda esses métodos de ajuda. Você vai ver os wrappers em detalhe em Wrappers e Autoboxing.

Brinque no JShell: teste Boolean.parseBoolean("TRUE"), Boolean.parseBoolean("sim"), e crie int idade = 30 para perguntar idade >= 18 && idade < 65. O JShell real responde assim:

$ jshell
|  Welcome to JShell -- Version 25.0.4.1
|  For an introduction type: /help intro

jshell> Boolean.parseBoolean("TRUE")
$1 ==> true

jshell> Boolean.parseBoolean("sim")
$2 ==> false

jshell> int idade = 30
idade ==> 30

jshell> idade >= 18 && idade < 65
$4 ==> true

jshell> /exit
|  Goodbye

Quando dá errado

error: incompatible types: int cannot be converted to boolean

Este código tem um erro de propósito.

public class Main {
    public static void main(String[] args) {
        boolean ligado = 1;
        System.out.println(ligado);
    }
}
$ javac Main.java
Main.java:3: error: incompatible types: int cannot be converted to boolean
        boolean ligado = 1;
                         ^
1 error

O que aconteceu: em algumas linguagens (C, Python, JavaScript), 1 vale como verdadeiro e 0 como falso. Em Java, não: boolean só aceita true e false.

Como resolver: boolean ligado = true;. Se você tem um número, faça a pergunta: boolean ligado = codigo == 1;.

error: incompatible types: String cannot be converted to boolean

Este código tem um erro de propósito.

public class Main {
    public static void main(String[] args) {
        boolean ativo = "true";
        System.out.println(ativo);
    }
}
$ javac Main.java
Main.java:3: error: incompatible types: String cannot be converted to boolean
        boolean ativo = "true";
                        ^
1 error

O que aconteceu: com aspas, "true" é um texto, não o valor true.

Como resolver: tire as aspas (true) ou, se o texto vem de fora, Boolean.parseBoolean("true").

error: bad operand types for binary operator '<='

Este código tem um erro de propósito.

public class Main {
    public static void main(String[] args) {
        int nota = 5;
        boolean entre = 0 <= nota <= 10;
        System.out.println(entre);
    }
}
$ javac Main.java
Main.java:4: error: bad operand types for binary operator '<='
        boolean entre = 0 <= nota <= 10;
                                  ^
  first type:  boolean
  second type: int
1 error

O que aconteceu: o Java faz uma comparação por vez, da esquerda para a direita. 0 <= nota virou true; depois tentou true <= 10, comparando um boolean (first type) com um int (second type), o que não existe.

Como resolver: duas perguntas ligadas por &&: nota >= 0 && nota <= 10.

error: illegal start of type (pergunta pela metade)

Este código tem um erro de propósito.

public class Main {
    public static void main(String[] args) {
        int idade = 20;
        boolean ok = idade > 18 & < 65;
        System.out.println(ok);
    }
}
$ javac Main.java
Main.java:4: error: illegal start of type
        boolean ok = idade > 18 & < 65;
                                    ^
1 error

O que aconteceu: em português dizemos "idade maior que 18 e menor que 65", sem repetir "idade". Em Java, cada lado do operador precisa de uma pergunta completa. O javac encontrou < onde esperava um valor. (Repare também que foi usado &, um só, em vez de &&; o & sozinho existe, mas não faz curto-circuito.)

Como resolver: idade > 18 && idade < 65.

error: ';' expected com and ou or

Este código tem um erro de propósito.

public class Main {
    public static void main(String[] args) {
        int idade = 20;
        boolean adulto = idade >= 18 and idade < 65;
        System.out.println(adulto);
    }
}
$ javac Main.java
Main.java:4: error: ';' expected
        boolean adulto = idade >= 18 and idade < 65;
                                    ^
Main.java:4: error: ';' expected
        boolean adulto = idade >= 18 and idade < 65;
                                              ^
Main.java:4: error: illegal start of type
        boolean adulto = idade >= 18 and idade < 65;
                                                 ^
3 errors

O que aconteceu: and, or e not são palavras do Python, não do Java. O javac achou que a linha terminava em 18 e pediu um ;.

Como resolver: &&, || e !.

NullPointerException numa condição com &&

O que aconteceu: a pergunta que usa o objeto veio antes da que verifica se ele existe: nome.length() > 0 && nome != null.

Como resolver: inverta a ordem: nome != null && nome.length() > 0.


Referência

EscritaSignificadoExemplo
boolean b = expr;Guarda a respostaboolean maior = idade >= 18;
a && bE (curto-circuito)idade >= 18 && temCarteira
a || bOu (curto-circuito)dia.equals("sábado") || dia.equals("domingo")
!aNão!chovendo
x >= min && x <= maxDentro da faixanota >= 0 && nota <= 10
x < min || x > maxFora da faixanota < 0 || nota > 10
!(a && b) = !a || !bDe Morgan
a != b (ou a ^ b)Ou exclusivo
Boolean.parseBoolean(s)Texto → boolean (só "true" dá true)Boolean.parseBoolean("TRUE") → true
String.valueOf(b)boolean → textoString.valueOf(false) → "false"

Exercícios

Missão final: uma senha é válida se tem pelo menos 8 caracteres, não contém espaço e não é igual ao usuário. Crie as três variáveis boolean e a variável valida, que junta as três. Mostre as quatro, no formato abaixo. Com a senha "ana 2026", a saída é:
Tamanho ok: true
Sem espaço: false
Diferente do usuário: true
Senha válida: false

public class Main {
    public static void main(String[] args) {
        String usuario = "ana";
        String senha = "ana 2026";
        // crie tamanhoOk, semEspaco, diferente e valida
    }
}
public class Main {
    public static void main(String[] args) {
        String usuario = "ana";
        String senha = "ana 2026";
        boolean tamanhoOk = senha.length() >= 8;
        boolean semEspaco = !senha.contains(" ");
        boolean diferente = !senha.equals(usuario);
        boolean valida = tamanhoOk && semEspaco && diferente;
        System.out.println("Tamanho ok: " + tamanhoOk);
        System.out.println("Sem espaço: " + semEspaco);
        System.out.println("Diferente do usuário: " + diferente);
        System.out.println("Senha válida: " + valida);
    }
}

1. Faixa

Complete para saber se temperatura está entre 20 e 30 (incluindo os dois):

boolean agradavel = temperatura >= 20 temperatura <= 30;

2. Inverter

Complete para que diaUtil seja o contrário de fimDeSemana:

boolean diaUtil = ;

3. Texto para boolean

Quanto vale Boolean.parseBoolean("verdadeiro")?

4. Com int x = 15;, quanto vale x > 10 && x < 12 || x == 15?

5. Qual expressão não lança exceção quando texto é null?

6. Qual expressão é sempre false, para qualquer nota?


Resumo

  • Uma expressão booleana é uma pergunta cuja resposta é true ou false: comparações, métodos como equals e isEmpty, variáveis boolean.
  • Dê às variáveis boolean nomes que se leem como perguntas: podeVotar, temDesconto.
  • && exige as duas; || basta uma; ! inverte. Faixa: x >= min && x <= max (nunca min <= x <= max).
  • && e || param assim que sabem a resposta (curto-circuito): ponha primeiro a pergunta que protege, como nome != null.
  • Use if (aprovado) e if (!aprovado), sem == true.
  • Boolean.parseBoolean só reconhece "true" (qualquer caixa); todo o resto vira false.