English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Neste tutorial, você aprenderá a usar Java para lidar com exceções. Para lidar com exceções, usaremos o bloco try...catch...finally.
No tutorial anterior, aprendemos sobre exceções. Exceções são eventos inesperados que ocorrem durante a execução do programa.
No Java, usamos componentes de tratamento de exceções try, catch e bloco finally para lidar com exceções.
Para capturar e lidar com exceções, colocamos o bloco de código try...catch...finally ao redor do código que pode gerar exceções. O bloco finally é opcional.
A sintaxe de try...catch...finally é:
try {}} // Código catch (ExceptionType e) { // Bloco de captura } finally { //Bloco finally }
O código que pode gerar exceções deve ser colocado dentro do bloco try.
Cada bloco try deve ser seguido imediatamente por um bloco catch ou finally. Quando uma exceção ocorre, ela será capturada pelo bloco que segue o bloco try.
O bloco catch não pode ser usado sozinho, deve seguir imediatamente após o bloco try.
class Main { public static void main(String[] args) { try {}} int divideByZero = 5 / 0; System.out.println("O restante do código dentro do bloco try"); } catch (ArithmeticException e) { System.out.println("ArithmeticException => "); + e.getMessage()); } } }
Resultados de saída
ArithmeticException => / por zero
Neste exemplo
Nós dividimos o número por zero dentro do bloco try. Isso gera um ArithmeticException.
Quando uma exceção ocorre, o programa pula o restante do código dentro do bloco try.
Aqui, criamos um bloco catch para lidar com ArithmeticException. Portanto, executamos as instruções dentro do bloco catch.
Se todas as instruções dentro do bloco try não gerarem exceções, o bloco catch é pulado.
Para cada bloco try, pode haver zero ou mais bloco catch.
O tipo de parâmetro de cada catch bloco indica o tipo de exceção que pode ser tratada. Múltiplos bloco catch nos permitem lidar de diferentes maneiras com cada exceção.
class ListOfNumbers { public int[] arrayOfNumbers = new int[10]; public void writeList() { try {}} arrayOfNumbers[10= 11; catch (NumberFormatException e1) { System.out.println("NumberFormatException => ") + e1.getMessage()); } catch (IndexOutOfBoundsException e2) { System.out.println("IndexOutOfBoundsException => "); + e2.getMessage()); } } } class Main { public static void main(String[] args) { ListOfNumbers list = new ListOfNumbers(); list.writeList(); } }
Resultados de saída
IndexOutOfBoundsException => Index 10 fora dos limites para comprimento 10
Neste exemplo, declaramos um array de tamanho10 um array de inteiros arrayOfNumbers.}}
Sabemos que os índices de array sempre começam em 0. Portanto, quando tentamos atribuir a índice10Ocorre IndexOutOfBoundsException ao atribuir um valor, porque os limites do array arrayOfNumbers são de 0 a9.
Quando ocorre uma exceção no bloco try
A exceção é lançada para o primeiro bloco catch. O primeiro bloco catch não lida com a exceção IndexOutOfBoundsException, então é passada para o próximo bloco catch.
O segundo bloco catch no exemplo acima é o tratador de exceções apropriado, pois ele lida com IndexOutOfBoundsException. Portanto, ele é executado.
Para cada bloco try, pode haver apenas um bloco finally.
O bloco finally é opcional. Mas, se estiver definido, sempre será executado (mesmo que não ocorra exceção).
Se ocorrer uma exceção, é executado após o bloco try...catch. Se não ocorrer nenhuma exceção, é executado após o bloco try.
A sintaxe básica do bloco finally é:
try {}} //código } catch (ExceçãoType1 e1) { // catch bloco } catch (ExceçãoType1 e2) { // catch bloco } finally { //O bloco finally sempre é executado }
class Main { public static void main(String[] args) { try {}} int divideByZero = 5 / 0; } catch (ArithmeticException e) { System.out.println("ArithmeticException => "); + e.getMessage()); } finally { System.out.println("O bloco finally sempre é executado"); } } }
Resultados de saída
ArithmeticException => / por zero O bloco finally sempre é executado
Neste exemplo, dividiremos um número por zero. Isso gera uma ArithmeticException capturada pelo bloco catch, e o bloco finally sempre é executado.
Usar o bloco finally é uma boa prática. Isso porque ele contém código importante para limpeza, por exemplo
Código que pode ser pular inesperadamente devido a instruções return, continue ou break
Fechar arquivos ou conexões
Já mencionamos que o finally sempre é executado, geralmente é assim. Mas, em alguns casos, o bloco finally não é executado:
Usamos o método System.exit()
Ocorreu uma exceção no bloco finally
A thread foi encerrada
Vamos dar um exemplo, tentamos usar FileWriter para criar um novo arquivo e usar PrintWriter para escrever dados.
import java.io.*; class ListOfNumbers { private int[] list = new int[10]; public ListOfNumbers() { //armazenar valores inteiros no array de lista for (int i = 0; i < 10; i++) { list[i] = i; } } } public void writeList() { PrintWriter out = null; try {}} System.out.println("Entrar no bloco try"); //criar um novo arquivo OutputFile.txt out = new PrintWriter(new FileWriter("OutputFile.txt")); //escrever valores do array de lista em um arquivo recém-criado for (int i = 0; i < 10; i++) { out.println("Valor em: "); + i + " = "; + list[i]; } } catch (IndexOutOfBoundsException e1) { System.out.println("IndexOutOfBoundsException => "); + e1.getMessage()); } catch (IOException e2) { System.out.println("IOException => "); + e2.getMessage()); } finally { //verificar se o PrintWriter foi aberto if (out != null) { System.out.println("Fechar PrintWriter"); out.close(); } else { System.out.println("PrintWriter não pode ser aberto"); } } } } class Main { public static void main(String[] args) { ListOfNumbers list = new ListOfNumbers(); list.writeList(); } }
Quando você executar este programa, podem ocorrer duas possibilidades:
ocorreu uma exceção no bloco try
bloco try executado normalmente
Pode ocorrer uma exceção ao criar um novo FileWriter. Se não for possível criar ou escrever no arquivo especificado, uma IOException será lançada.
Quando ocorrer uma exceção, obteremos a seguinte saída.
Entrar no comando try IOException => OutputFile.txt O PrintWriter não pode ser aberto
Quando não ocorrer exceção e o bloco try executar normalmente, obteremos a seguinte saída.
Entrar no comando try Fechar PrintWriter
Será criado um OutputFile.txt, contendo o seguinte
Value at: 0 = 0 Value at: 1 = 1 Value at: 2 = 2 Value at: 3 = 3 Value at: 4 = 4 Value at: 5 = 5 Value at: 6 = 6 Value at: 7 = 7 Value at: 8 = 8 Value at: 9 = 9
Vamos tentar entender o fluxo de tratamento de exceções em detalhes com a ajuda do exemplo acima.
A figura acima descreve o fluxo de execução do programa quando ocorre uma exceção ao criar um novo FileWriter.
Para encontrar o método onde ocorreu a exceção, o método main chama o método writeList(), que, em seguida, chama o método FileWriter() para criar um novo arquivo OutputFile.txt.
Quando ocorre uma exceção, o sistema de tempo de execução pula o resto do código no bloco try.
Ele começa a procurar na ordem inversa da pilha de chamadas para encontrar o programa de tratamento de exceção apropriado.
Aqui, o FileWriter não tem programa de tratamento de exceções, então o sistema de tempo de execução verifica o próximo método na pilha de chamadas, ou seja, writeList.
O método writeList tem dois programas de tratamento de exceções: um para IndexOutOfBoundsException e outro para IOException.
Então, o sistema lida com esses programas de tratamento uma após a outra.
No exemplo, o primeiro programa de tratamento lida com IndexOutOfBoundsException. Isso não coincide com o IOException gerado pelo bloco try.
Portanto, verifique qual é o próximo programa de tratamento de IOException. Se coincidir com o tipo de exceção gerada, então será executado o código no bloco catch correspondente.
Após a execução do programa de tratamento de exceções, será executado o bloco finally.
Neste cenário, devido à exceção no FileWriter, o objeto PrintWriter out nunca foi aberto, portanto, não é necessário fechá-lo.
Agora, vamos supor que, ao executar o programa, não haja exceção e o bloco try execute normalmente. Neste caso, será criado e escrito um OutputFile.txt.
É sabido que a execução do bloco finally não está relacionada ao tratamento de exceções. Como não houve exceção, o PrintWriter foi aberto e precisa ser fechado. Isso é feito pela instrução out.close() no bloco finally.
A partir do Java SE 7A partir da versão e superior, podemos capturar mais de um tipo de exceção com um bloco catch.
Dessa forma, pode-se reduzir a repetição de código e aumentar a simplicidade e eficiência do código.
Cada tipo de exceção que pode ser tratada pelo bloco catch é separado por um pipe (|).
Sua sintaxe é:
try {}} // código } catch (ExceçãoType1 | ExceçãoType2 ex) { // bloco catch }
Para obter mais informações, acesseJava captura múltiplas exceções.
try-com-A sentença resources é uma sentença try que possui uma ou mais declarações de recursos.
Sua sintaxe é:
try (declaração de recurso) { // uso do recurso } catch (ExceptionType e1) { // bloco catch }
Os recursos são objetos que devem ser fechados no final do programa. Deve ser declarado e inicializado dentro da sentença try.
Vamos dar um exemplo.
try (PrintWriter out = new PrintWriter(new FileWriter("OutputFile.txt"))) { // uso do recurso }
try-com-Sentença resources também é conhecida comoGestão de Recursos Automática. Esta sentença fecha automaticamente todos os recursos no final da sentença.
Para obter mais informações, acesseJava try-com-Sentença resources.