Menu
Coddy logo textTech

Erros Checked vs Unchecked

Parte da seção Programação Orientada a Objetos do Journey de Java da Coddy. Lição 61 de 87.

Você viu que a hierarquia de exceções do Java se divide em diferentes ramificações. A principal distinção que você precisa entender é entre exceções verificadas e não verificadas. Isso afeta como você deve tratá-las no seu código.

Exceções verificadas são exceções que o compilador obriga você a tratar. Elas estendem Exception diretamente (não por meio de RuntimeException). Você deve capturá-las ou declará-las com throws:

// Deve tratar IOException - é checked
public void readFile(String path) throws IOException {
    FileReader reader = new FileReader(path);  // Pode lançar IOException
}

// Ou capture-a
public void readFileSafe(String path) {
    try {
        FileReader reader = new FileReader(path);
    } catch (IOException e) {
        System.out.println("File error: " + e.getMessage());
    }
}

exceções não verificadas estendem RuntimeException. O compilador não exige que você as trate. Elas normalmente indicam erros de programação, como referências nulas ou acesso inválido a arrays:

// Nenhuma declaração throws necessária
public int divide(int a, int b) {
    return a / b;  // Pode lançar ArithmeticException (não verificada)
}

String name = null;
name.length();  // NullPointerException (não verificada)

Ao criar exceções personalizadas, escolha a classe pai com base em como você deseja que os chamadores as tratem. Use exceções verificadas para condições recuperáveis que o chamador deve antecipar. Use exceções não verificadas para erros de programação que não deveriam ocorrer em um código correto.

challenge icon

Desafio

Fácil

Vamos criar um sistema de verificação de idade que demonstra a principal diferença entre exceções verificadas e não verificadas! Você criará exceções personalizadas dos dois tipos e verá como o compilador as trata de maneira diferente.

Você organizará seu código em quatro arquivos:

  • InvalidAgeException.java: Crie uma exceção verificada para falhas na validação da idade. Essa exceção deve estender Exception diretamente, o que significa que os chamadores serão obrigados a tratá-la. Inclua um construtor que aceite uma mensagem e a passe para a classe pai.
  • NegativeAgeException.java: Crie uma exceção não verificada para quando alguém fornecer uma idade negativa (um erro de programação que não deveria ocorrer com uma entrada correta). Ela deve estender RuntimeException. Inclua um construtor que aceite e passe uma mensagem para a classe pai.
  • AgeVerifier.java: Crie uma classe que valide idades usando os dois tipos de exceção. Inclua dois métodos estáticos:

    verifyAge(int age) - Este método deve lançar NegativeAgeException (não verificada) com a mensagem "Age cannot be negative: [age]" se a idade for menor que 0. Se a idade for menor que 18, lance InvalidAgeException (verificada) com a mensagem "Must be 18 or older: [age]". Caso contrário, imprima Age [age] verified successfully. Como este método lança uma exceção verificada, você deve declará-lo com throws InvalidAgeException.

    verifyAgeUncheckedOnly(int age) - Este método usa apenas exceções não verificadas. Se a idade for negativa, lance NegativeAgeException com o mesmo formato de mensagem. Se a idade for menor que 18, lance uma IllegalArgumentException com a mensagem "Too young: [age]". Caso contrário, imprima Age [age] verified (unchecked method). Observe que este método não precisa de uma declaração throws!

  • Main.java: Reúna seu sistema de verificação! Você receberá uma entrada: uma idade (inteiro).

    Primeiro, imprima === Checked Exception Method === e chame verifyAge com a idade de entrada. Como ele lança uma exceção verificada, você deve envolvê-lo em um try-catch. Capture InvalidAgeException e imprima Checked exception caught: [message]. Capture também NegativeAgeException e imprima Unchecked exception caught: [message].

    Em seguida, imprima uma linha em branco e === Unchecked Exception Method ===. Chame verifyAgeUncheckedOnly com a mesma idade. Embora esse método possa lançar exceções, você não é obrigado a capturá-las. No entanto, envolva-o em um try-catch mesmo assim para tratar os erros de maneira adequada. Capture NegativeAgeException e imprima Runtime exception caught: [message]. Capture IllegalArgumentException e imprima Illegal argument caught: [message].

Você receberá uma entrada: um inteiro que representa a idade a ser verificada.

Observe a principal diferença: o método com a exceção verificada exige uma declaração throws e obriga os chamadores a tratá-la, enquanto o método não verificado é compilado normalmente sem nenhum tratamento de exceção. Essa é a distinção fundamental entre exceções verificadas e não verificadas em Java!

Experimente você mesmo

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int age = scanner.nextInt();
        
        // TODO: Test the checked exception method
        // Print: "=== Checked Exception Method ==="
        // Chame AgeVerifier.verifyAge(age) em um try-catch
        // - Catch InvalidAgeException: print "Checked exception caught: [message]"
        // - Catch NegativeAgeException: print "Unchecked exception caught: [message]"
        
        
        // TODO: Print a blank line, then "=== Unchecked Exception Method ==="
        // Chame AgeVerifier.verifyAgeUncheckedOnly(age) em um try-catch
        // - Catch NegativeAgeException: print "Runtime exception caught: [message]"
        // - Catch IllegalArgumentException: print "Illegal argument caught: [message]"
        
    }
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos

Pratique por conta própria: Compilador de Java online