Menu
Coddy logo textTech

Padrão Try With Resources

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

Ao trabalhar com recursos como fluxos de arquivos ou conexões de banco de dados, você deve sempre fechá-los quando terminar. Caso contrário, você corre o risco de causar vazamentos de memória. A abordagem tradicional usa um bloco finally, mas é prolixa e propensa a erros.

A instrução try-with-resources do Java fecha os recursos automaticamente quando o bloco é concluído. Qualquer classe que implemente a interface AutoCloseable pode ser usada com esta sintaxe:

// Abordagem tradicional - verbosa e arriscada
BufferedReader reader = null;
try {
    reader = new BufferedReader(new FileReader("file.txt"));
    String line = reader.readLine();
} finally {
    if (reader != null) {
        reader.close();  // Também poderia lançar uma exceção!
    }
}

// Try-with-resources - limpo e seguro
try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"))) {
    String line = reader.readLine();
}  // Fechado automaticamente aqui

Você pode gerenciar vários recursos separando-os com ponto e vírgula. Eles são fechados na ordem inversa da declaração:

try (FileReader fr = new FileReader("input.txt");
     BufferedReader br = new BufferedReader(fr)) {
    // Use ambos os recursos
}  // br fechado primeiro, depois fr

Para criar sua própria classe com fechamento automático, implemente a interface AutoCloseable e seu único método close():

public class DatabaseConnection implements AutoCloseable {
    public DatabaseConnection() {
        System.out.println("Connection opened");
    }
    
    @Override
    public void close() {
        System.out.println("Connection closed");
    }
}

Este padrão garante que os recursos sejam sempre liberados corretamente, mesmo que ocorram exceções durante o processamento.

challenge icon

Desafio

Fácil

Vamos criar um sistema de gerenciamento de recursos que demonstra o poder de try-with-resources! Você criará classes personalizadas que podem ser fechadas automaticamente, simulando o gerenciamento de conexões e sessões e garantindo que elas sejam sempre devidamente encerradas.

Você organizará seu código em três arquivos:

  • Connection.java: Crie uma classe que simule uma conexão com um banco de dados. Sua classe Connection deve implementar AutoCloseable. Ela precisa de um campo privado para o nome da conexão (String), um construtor que receba o nome e imprima [name] connection opened, um método query(String sql) que imprima Executing on [name]: [sql] e o método obrigatório close() que imprima [name] connection closed.
  • Session.java: Crie outra classe que possa ser fechada automaticamente, simulando uma sessão de usuário. Sua classe Session também deve implementar AutoCloseable. Inclua um campo privado para o nome de usuário (String), um construtor que receba o nome de usuário e imprima Session started for [username], um método performAction(String action) que imprima [username] performed: [action] e um método close() que imprima Session ended for [username].
  • Main.java: Reúna seu sistema de gerenciamento de recursos! Você receberá três entradas: um nome de conexão, um nome de usuário e uma ação a ser executada.

    Primeiro, demonstre o gerenciamento de um único recurso. Imprima === Single Resource === e, em seguida, use try-with-resources para criar uma Connection com o nome fornecido. Dentro do bloco try, chame query("SELECT * FROM users"). A conexão deverá ser fechada automaticamente quando o bloco terminar.

    Em seguida, demonstre múltiplos recursos. Imprima uma linha em branco e depois === Multiple Resources ===. Use try-with-resources com uma Connection (usando o mesmo nome) e uma Session (usando o nome de usuário), declaradas nessa ordem e separadas por ponto e vírgula. Dentro do bloco try, primeiro chame query("INSERT INTO logs") na conexão e, em seguida, chame performAction com a ação de entrada na sessão. Observe como os recursos são fechados na ordem inversa!

Você receberá três entradas, nesta ordem: nome da conexão (String), nome de usuário (String) e ação (String).

Observe como try-with-resources elimina a necessidade de chamadas explícitas a close e de blocos finally. Os recursos têm garantia de serem fechados mesmo que ocorram exceções, e múltiplos recursos são fechados na ordem inversa da declaração!

Experimente você mesmo

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String connectionName = scanner.nextLine();
        String username = scanner.nextLine();
        String action = scanner.nextLine();
        
        // === Single Resource ===
        // TODO: Imprima o cabeçalho
        // TODO: Use try-with-resources para criar uma Connection
        // TODO: Inside the try block, call query("SELECT * FROM users")
        
        // === Multiple Resources ===
        // TODO: Imprima uma linha em branco e o cabeçalho
        // TODO: Use try-with-resources com Connection e Session
        // TODO: Dentro do bloco try:
        //       - Call query("INSERT INTO logs") on the connection
        //       - Chame performAction com a action de entrada na session
        
    }
}
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