Java - Exceções
Uma exceção (ou evento excepcional) é um problema que surge durante a execução de um programa. Quando uma Exceção ocorre o fluxo normal do programa é interrompido e o programa/aplicativo termina de forma anormal, o que não é recomendado, portanto, essas exceções devem ser tratadas.
Uma exceção pode ocorrer por vários motivos diferentes. A seguir estão alguns cenários em que ocorre uma exceção.
-
Um usuário inseriu um dado inválido.
-
Um arquivo que precisa ser aberto não pode ser encontrado.
-
Uma conexão de rede foi perdida no meio das comunicações ou a JVM ficou sem memória.
Algumas dessas exceções são causadas por erro do usuário, outras por erro do programador e outras por recursos físicos que falharam de alguma maneira.
Com base nisso, temos três categorias de Exceções. Você precisa entendê-los para saber como o tratamento de exceções funciona em Java.
-
Exceções verificadas − Uma exceção verificada é uma exceção que é verificada (notificada) pelo compilador em tempo de compilação, também são chamadas de exceções de tempo de compilação. Essas exceções não podem ser simplesmente ignoradas, o programador deve cuidar (tratar) dessas exceções.
Por exemplo, se você usar o FileReader class em seu programa para ler dados de um arquivo, se o arquivo especificado em seu construtor não existir, então uma FileNotFoundException ocorre e o compilador solicita que o programador trate a exceção.
Exemplo
Demonstração ao vivoimport java.io.File; import java.io.FileReader; public class FilenotFound_Demo { public static void main(String args[]) { File file = new File("E://file.txt"); FileReader fr = new FileReader(file); } }
Se você tentar compilar o programa acima, obterá as seguintes exceções.
Saída
C:\>javac FilenotFound_Demo.java FilenotFound_Demo.java:8: error: unreported exception FileNotFoundException; must be caught or declared to be thrown FileReader fr = new FileReader(file); ^ 1 error
Observação − Uma vez que os métodos read() e fechar() da classe FileReader lança IOException, você pode observar que o compilador notifica para manipular IOException, juntamente com FileNotFoundException.
-
Exceções não verificadas − Uma exceção não verificada é uma exceção que ocorre no momento da execução. Eles também são chamados de Exceções de tempo de execução . Isso inclui bugs de programação, como erros de lógica ou uso indevido de uma API. As exceções de tempo de execução são ignoradas no momento da compilação.
Por exemplo, se você declarou um array de tamanho 5 em seu programa e está tentando chamar o 6 th elemento da matriz, em seguida, um ArrayIndexOutOfBoundsExceptionexception ocorre.
Exemplo
Demonstração ao vivopublic class Unchecked_Demo { public static void main(String args[]) { int num[] = {1, 2, 3, 4}; System.out.println(num[5]); } }
Se você compilar e executar o programa acima, receberá a seguinte exceção.
Saída
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5 at Exceptions.Unchecked_Demo.main(Unchecked_Demo.java:8)
-
Erros − Não são exceções, mas problemas que surgem fora do controle do usuário ou do programador. Erros são normalmente ignorados em seu código porque você raramente pode fazer algo sobre um erro. Por exemplo, se ocorrer um estouro de pilha, ocorrerá um erro. Eles também são ignorados no momento da compilação.
Hierarquia de exceção
Todas as classes de exceção são subtipos da classe java.lang.Exception. A classe de exceção é uma subclasse da classe Throwable. Além da classe de exceção, há outra subclasse chamada Error que é derivada da classe Throwable.
Erros são condições anormais que ocorrem em caso de falhas graves, que não são tratadas pelos programas Java. Erros são gerados para indicar erros gerados pelo ambiente de tempo de execução. Exemplo:JVM está sem memória. Normalmente, os programas não podem se recuperar de erros.
A classe Exception possui duas subclasses principais:classe IOException e classe RuntimeException.
A seguir está uma lista das exceções incorporadas do Java marcadas e desmarcadas mais comuns.
Métodos de exceção
A seguir está a lista de métodos importantes disponíveis na classe Throwable.
Nº Sr. | Método e descrição |
---|---|
1 | string pública getMessage() Retorna uma mensagem detalhada sobre a exceção que ocorreu. Esta mensagem é inicializada no construtor Throwable. |
2 | getCause de lançamento público() Retorna a causa da exceção representada por um objeto Throwable. |
3 | String pública toString() Retorna o nome da classe concatenado com o resultado de getMessage(). |
4 | public void printStackTrace() Imprime o resultado de toString() junto com o rastreamento de pilha para System.err, o fluxo de saída de erro. |
5 | StackTraceElement público [] getStackTrace() Retorna uma matriz contendo cada elemento no rastreamento de pilha. O elemento no índice 0 representa o topo da pilha de chamadas e o último elemento na matriz representa o método na parte inferior da pilha de chamadas. |
6 | Público Throwable fillInStackTrace() Preenche o rastreamento de pilha deste objeto Throwable com o rastreamento de pilha atual, adicionando qualquer informação anterior no rastreamento de pilha. |
Capturando exceções
Um método captura uma exceção usando uma combinação do try e pegue palavras-chave. Um bloco try/catch é colocado em torno do código que pode gerar uma exceção. O código dentro de um bloco try/catch é chamado de código protegido, e a sintaxe para usar try/catch se parece com a seguinte −
Sintaxe
try { // Protected code } catch (ExceptionName e1) { // Catch block }
O código que é propenso a exceções é colocado no bloco try. Quando ocorre uma exceção, essa exceção ocorrida é tratada pelo bloco catch associado a ela. Cada bloco try deve ser imediatamente seguido por um bloco catch ou por um bloco finally.
Uma instrução catch envolve declarar o tipo de exceção que você está tentando capturar. Se ocorrer uma exceção no código protegido, o bloco catch (ou blocos) que segue o try é verificado. Se o tipo de exceção que ocorreu está listado em um bloco catch, a exceção é passada para o bloco catch da mesma forma que um argumento é passado para um parâmetro de método.
Exemplo
O seguinte é um array declarado com 2 elementos. Em seguida, o código tenta acessar o 3 rd elemento do array que lança uma exceção.
Demonstração ao vivo
// File Name : ExcepTest.java import java.io.*; public class ExcepTest { public static void main(String args[]) { try { int a[] = new int[2]; System.out.println("Access element three :" + a[3]); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("Exception thrown :" + e); } System.out.println("Out of the block"); } }
Isso produzirá o seguinte resultado -
Saída
Exception thrown :java.lang.ArrayIndexOutOfBoundsException: 3 Out of the block
Vários blocos de captura
Um bloco try pode ser seguido por vários blocos catch. A sintaxe para vários blocos catch se parece com o seguinte -
Sintaxe
try { // Protected code } catch (ExceptionType1 e1) { // Catch block } catch (ExceptionType2 e2) { // Catch block } catch (ExceptionType3 e3) { // Catch block }
As instruções anteriores demonstram três blocos catch, mas você pode ter qualquer número deles após uma única tentativa. Se ocorrer uma exceção no código protegido, a exceção será lançada para o primeiro bloco catch na lista. Se o tipo de dados da exceção lançada corresponder a ExceptionType1, ele será capturado lá. Caso contrário, a exceção passa para a segunda instrução catch. Isso continua até que a exceção seja capturada ou caia em todas as capturas; nesse caso, o método atual interrompe a execução e a exceção é lançada para o método anterior na pilha de chamadas.
Exemplo
Aqui está o segmento de código mostrando como usar várias instruções try/catch.
try { file = new FileInputStream(fileName); x = (byte) file.read(); } catch (IOException i) { i.printStackTrace(); return -1; } catch (FileNotFoundException f) // Not valid! { f.printStackTrace(); return -1; }
Capturando vários tipos de exceções
Desde o Java 7, você pode manipular mais de uma exceção usando um único bloco catch, esse recurso simplifica o código. Aqui está como você faria isso -
catch (IOException|FileNotFoundException ex) { logger.log(ex); throw ex;
As palavras-chave de lançamentos
Se um método não trata uma exceção verificada, o método deve declará-la usando o throws palavra-chave. A palavra-chave throws aparece no final da assinatura de um método.
Você pode lançar uma exceção, seja uma recém-instanciada ou uma exceção que você acabou de capturar, usando o comando throw palavra-chave.
Tente entender a diferença entre throws e throw keywords, throws é usado para adiar o tratamento de uma exceção verificada e lançar é usado para invocar uma exceção explicitamente.
O método a seguir declara que lança uma RemoteException -
Exemplo
import java.io.*; public class className { public void deposit(double amount) throws RemoteException { // Method implementation throw new RemoteException(); } // Remainder of class definition }
Um método pode declarar que lança mais de uma exceção, nesse caso as exceções são declaradas em uma lista separada por vírgulas. Por exemplo, o método a seguir declara que lança um RemoteException e um InsufficientFundsException −
Exemplo
import java.io.*; public class className { public void withdraw(double amount) throws RemoteException, InsufficientFundsException { // Method implementation } // Remainder of class definition }
O Bloco Final
O bloco finally segue um bloco try ou um bloco catch. Um bloco de código finalmente sempre é executado, independentemente da ocorrência de uma exceção.
O uso de um bloco finally permite executar qualquer instrução do tipo cleanup que você deseja executar, não importa o que aconteça no código protegido.
Um bloco finally aparece no final dos blocos catch e tem a seguinte sintaxe -
Sintaxe
try { // Protected code } catch (ExceptionType1 e1) { // Catch block } catch (ExceptionType2 e2) { // Catch block } catch (ExceptionType3 e3) { // Catch block }finally { // The finally block always executes. }
Exemplo
Demonstração ao vivopublic class ExcepTest { public static void main(String args[]) { int a[] = new int[2]; try { System.out.println("Access element three :" + a[3]); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("Exception thrown :" + e); }finally { a[0] = 6; System.out.println("First element value: " + a[0]); System.out.println("The finally statement is executed"); } } }
Isso produzirá o seguinte resultado -
Saída
Exception thrown :java.lang.ArrayIndexOutOfBoundsException: 3 First element value: 6 The finally statement is executed
Observe o seguinte -
-
Uma cláusula catch não pode existir sem uma instrução try.
-
Não é obrigatório ter cláusulas finally sempre que um bloco try/catch estiver presente.
-
O bloco try não pode estar presente sem a cláusula catch ou finally.
-
Qualquer código não pode estar presente entre os blocos try, catch, finally.
O teste com recursos
Geralmente, quando usamos quaisquer recursos como streams, conexões, etc., temos que fechá-los explicitamente usando o bloco finally. No programa a seguir, estamos lendo dados de um arquivo usando FileReader e estamos fechando usando o bloco finally.
Exemplo
import java.io.File; import java.io.FileReader; import java.io.IOException; public class ReadData_Demo { public static void main(String args[]) { FileReader fr = null; try { File file = new File("file.txt"); fr = new FileReader(file); char [] a = new char[50]; fr.read(a); // reads the content to the array for(char c : a) System.out.print(c); // prints the characters one by one } catch (IOException e) { e.printStackTrace(); }finally { try { fr.close(); } catch (IOException ex) { ex.printStackTrace(); } } } }
experimente com recursos , também conhecido como gerenciamento automático de recursos , é um novo mecanismo de manipulação de exceção que foi introduzido no Java 7, que fecha automaticamente os recursos usados no bloco try catch.
Para usar esta instrução, basta declarar os recursos necessários entre parênteses, e o recurso criado será fechado automaticamente no final do bloco. A seguir está a sintaxe da instrução try-with-resources.
Sintaxe
try(FileReader fr = new FileReader("file path")) { // use the resource } catch () { // body of catch } }
A seguir está o programa que lê os dados em um arquivo usando a instrução try-with-resources.
Exemplo
import java.io.FileReader; import java.io.IOException; public class Try_withDemo { public static void main(String args[]) { try(FileReader fr = new FileReader("E://file.txt")) { char [] a = new char[50]; fr.read(a); // reads the contentto the array for(char c : a) System.out.print(c); // prints the characters one by one } catch (IOException e) { e.printStackTrace(); } } }
Os pontos a seguir devem ser mantidos em mente ao trabalhar com a instrução try-with-resources.
-
Para usar uma classe com instrução try-with-resources, ela deve implementar AutoCloseable interface e fechar() método dele é invocado automaticamente em tempo de execução.
-
Você pode declarar mais de uma classe na instrução try-with-resources.
-
Enquanto você declara várias classes no bloco try da instrução try-with-resources, essas classes são fechadas na ordem inversa.
-
Exceto a declaração de recursos entre parênteses, tudo é igual ao bloco try/catch normal de um bloco try.
-
O recurso declarado em try é instanciado imediatamente antes do início do bloco try.
-
O recurso declarado no bloco try é declarado implicitamente como final.
Exceções definidas pelo usuário
Você pode criar suas próprias exceções em Java. Mantenha os seguintes pontos em mente ao escrever suas próprias classes de exceção -
-
Todas as exceções devem ser filhas de Throwable.
-
Se você deseja escrever uma exceção verificada que é automaticamente imposta pela regra Handle ou Declare, você precisa estender a classe Exception.
-
Se você quiser escrever uma exceção de tempo de execução, precisará estender a classe RuntimeException.
Podemos definir nossa própria classe Exception como abaixo -
class MyException extends Exception { }
Você só precisa estender a Exceção predefinida class para criar sua própria exceção. Estas são consideradas exceções verificadas. A seguinte InsufficientFundsException class é uma exceção definida pelo usuário que estende a classe Exception, tornando-a uma exceção verificada. Uma classe de exceção é como qualquer outra classe, contendo campos e métodos úteis.
Exemplo
// File Name InsufficientFundsException.java import java.io.*; public class InsufficientFundsException extends Exception { private double amount; public InsufficientFundsException(double amount) { this.amount = amount; } public double getAmount() { return amount; } }
Para demonstrar o uso de nossa exceção definida pelo usuário, a classe CheckingAccount a seguir contém um método retirar() que gera uma InsufficientFundsException.
// File Name CheckingAccount.java import java.io.*; public class CheckingAccount { private double balance; private int number; public CheckingAccount(int number) { this.number = number; } public void deposit(double amount) { balance += amount; } public void withdraw(double amount) throws InsufficientFundsException { if(amount <= balance) { balance -= amount; }else { double needs = amount - balance; throw new InsufficientFundsException(needs); } } public double getBalance() { return balance; } public int getNumber() { return number; } }
O programa BankDemo a seguir demonstra como invocar os métodos deposit() e retirar() de CheckingAccount.
// File Name BankDemo.java public class BankDemo { public static void main(String [] args) { CheckingAccount c = new CheckingAccount(101); System.out.println("Depositing $500..."); c.deposit(500.00); try { System.out.println("\nWithdrawing $100..."); c.withdraw(100.00); System.out.println("\nWithdrawing $600..."); c.withdraw(600.00); } catch (InsufficientFundsException e) { System.out.println("Sorry, but you are short $" + e.getAmount()); e.printStackTrace(); } } }
Compile todos os três arquivos acima e execute o BankDemo. Isso produzirá o seguinte resultado -
Saída
Depositing $500... Withdrawing $100... Withdrawing $600... Sorry, but you are short $200.0 InsufficientFundsException at CheckingAccount.withdraw(CheckingAccount.java:25) at BankDemo.main(BankDemo.java:13)
Exceções comuns
Em Java, é possível definir duas categorias de Exceções e Erros.
-
Exceções da JVM − São exceções/erros que são lançados exclusiva ou logicamente pela JVM. Exemplos:NullPointerException, ArrayIndexOutOfBoundsException, ClassCastException.
-
Exceções programáticas − Essas exceções são lançadas explicitamente pelo aplicativo ou pelos programadores da API. Exemplos:IllegalArgumentException, IllegalStateException.
Java