Bloco finally em Java: mitos, realidade e armadilhas
\n\nCada 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.
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.
Como funciona o finally? Exemplo básico
\n\nPara 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.
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\nSaída:
\nDentro do try\nBloco finally executado!\nO programa continua...\n\nTudo previsível. Mas o que acontecerá se no try ocorrer uma exceção que não for capturada?
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\nA saída surpreenderá os iniciantes:
\nTentando 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\nO 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.
Quando o finally NÃO é executado? Cenários reais
\n\nExistem pelo menos três situações em que o finally pode não ser executado. Lembre-se delas — isso economizará horas de depuração.
1. System.exit() — encerramento emergencial da JVM
\n\nO caso mais conhecido. Se no bloco try for chamado System.exit(0), a JVM será encerrada instantaneamente, e o finally não será executado.
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\nSaída:
\nIniciando trabalho...\n\nPor 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.
System.exit() no código, pare. É um mau hábito. Para encerrar o programa, use Blogs
Book Recommendations
Leia também
Dicionários em Python: criação e manipulação de chaves