O finally sempre é executado em Java? Análise completa com código

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Bloco finally em Java: mitos, realidade e armadilhas

\n\n

Cada desenvolvedor Java, do iniciante ao sênior, mais cedo ou mais tarde se depara com o bloco finally. Nos livros didáticos, escrevem: "Este bloco é executado sempre, independentemente de ocorrer uma exceção ou não". Parece uma garantia de ferro, certo? Mas vamos olhar nos bastidores.

\n\n

No StackOverflow, a pergunta "Does a finally block always get executed in Java?" reuniu milhares de visualizações e centenas de comentários. Programadores experientes debatem, iniciantes se perdem, e casos reais mostram: "sempre" não é uma verdade absoluta. Neste artigo, analisaremos todos os cenários, escreveremos código real e descobriremos quando o finally pode te decepcionar.

\n\n

Como funciona o finally? Exemplo básico

\n\n

Para começar — o clássico. O bloco finally é usado para liberar recursos: fechar arquivos, conexões com banco de dados, sockets. Ele é executado após o try (e catch, se houve exceção), mas antes que o controle saia do método.

\n\n
public class FinallyDemo {\n    public static void main(String[] args) {\n        try {\n            System.out.println("Dentro do try");\n            int result = 10 / 2; // Tudo ok\n        } catch (ArithmeticException e) {\n            System.out.println("Exceção capturada: " + e.getMessage());\n        } finally {\n            System.out.println("Bloco finally executado!");\n        }\n        System.out.println("O programa continua...");\n    }\n}
\n\n

Saída:

\n
Dentro do try\nBloco finally executado!\nO programa continua...
\n\n

Tudo previsível. Mas o que acontecerá se no try ocorrer uma exceção que não for capturada?

\n\n
public class FinallyWithUncaught {\n    public static void main(String[] args) {\n        try {\n            System.out.println("Tentando dividir por zero...");\n            int result = 10 / 0; // Exceção!\n        } finally {\n            System.out.println("Finally é executado ANTES da exceção subir");\n        }\n        // Esta linha não será executada\n        System.out.println("Esta linha não será impressa");\n    }\n}
\n\n

A saída surpreenderá os iniciantes:

\n
Tentando dividir por zero...\nFinally é executado ANTES da exceção subir\nException in thread "main" java.lang.ArithmeticException: / by zero\n    at FinallyWithUncaught.main(FinallyWithUncaught.java:5)
\n\n

O bloco finally foi executado, embora a exceção não tenha sido tratada. É exatamente esse comportamento que gerou o mito do "sempre". Mas vamos aprofundar.

\n\n

Quando o finally NÃO é executado? Cenários reais

\n\n

Existem pelo menos três situações em que o finally pode não ser executado. Lembre-se delas — isso economizará horas de depuração.

\n\n

1. System.exit() — encerramento emergencial da JVM

\n\n

O caso mais conhecido. Se no bloco try for chamado System.exit(0), a JVM será encerrada instantaneamente, e o finally não será executado.

\n\n
public class FinallyAndExit {\n    public static void main(String[] args) {\n        try {\n            System.out.println("Iniciando trabalho...");\n            System.exit(0); // JVM encerra aqui\n        } finally {\n            // Este código NÃO será executado!\n            System.out.println("Você achou que eu executaria? Pois não!");\n        }\n    }\n}
\n\n

Saída:

\n
Iniciando trabalho...
\n\n

Por que isso? Porque System.exit() interrompe a máquina virtual no nível do sistema operacional. Não é uma exceção — é uma ordem para "morrer". O bloco finally simplesmente não tem tempo de ser executado.

\n\n
\n Importante: Se você usa System.exit() no código, pare. É um mau hábito. Para encerrar o programa, use

Blogs

Book Recommendations