É difícil tornar um programa perfeito e inevitavelmente haverá várias anormalidades. Por exemplo, há um bug no próprio programa, como a impressora ficar sem papel quando o programa imprime ou não haver memória suficiente. Para resolver essas exceções, precisamos saber por que a exceção ocorreu. Para algumas exceções comuns, também podemos fornecer determinados planos de resposta. O tratamento de exceções na linguagem C é simplesmente implementado por meio de valores de retorno de função, mas o significado do valor de retorno geralmente é determinado por convenção. Os programadores precisam consultar uma grande quantidade de informações antes de encontrar um motivo vago. Linguagens orientadas a objetos, como C++, Java e Python, geralmente possuem mecanismos de tratamento de exceções mais complexos. O mecanismo de tratamento de exceções em Java é discutido aqui.
Tratamento de exceções Java
Tratamento de exceções
Uma grande parte do mecanismo de tratamento de exceções do Java vem do C++. Ele permite que os programadores ignorem problemas que não podem ser tratados temporariamente para continuar o desenvolvimento subsequente ou para permitir que o programa trate exceções de maneira mais inteligente.
Java usa alguns objetos especiais para representar condições anormais; esses objetos são chamados de objetos de exceção. Quando ocorre uma exceção, Java lançará um objeto representando a situação atual com base nas configurações predefinidas. O chamado lançamento é uma forma especial de retorno. O thread fará uma pausa e sairá das chamadas de método camada por camada até encontrar um manipulador de exceção. O manipulador de exceção pode capturar o objeto de exceção e decidir a próxima ação com base no objeto, como:
Lembre o usuário de lidar com exceções e continuar o programa para sair do programa
...
O manipulador de exceções se parece com isto, consiste em try, catch, finalmente e nos blocos seguintes. finalmente não é necessário.
tente { ...;}catch() { ...;}catch() { ...;}finalmente { ...;}
Este manipulador de exceções monitora o bloco do programa após a tentativa. Os parênteses catch possuem um parâmetro que representa o tipo de exceção a ser capturada. catch irá capturar o tipo correspondente e suas classes derivadas. O bloco de programa após try contém as operações a serem executadas para o tipo de exceção. O bloco de programa monitorado por try pode lançar mais de um tipo de exceção, portanto, um manipulador de exceção pode ter vários módulos catch. O bloco de programa após finalmente é um programa que deve ser executado independentemente de ocorrer uma exceção.
Colocamos programas que podem dar errado e precisam ser monitorados em try, e projetamos soluções para lidar com exceções em catch.
A seguir está um programa Java parcial que usa tratamento de exceções. A parte try do programa lê linhas de texto de um arquivo. Durante o processo de leitura do arquivo, pode ocorrer uma IOException:
BufferedReader br = new BufferedReader(new FileReader("file.txt"));tentar { StringBuilder sb = new StringBuilder(); ;sb.append("/n"); linha = br.readLine(); sb.toString();} catch(IOException e) { e.printStackTrace(); System.out.println("Problema de IO");}finalmente { br.close();}
Se capturarmos o objeto da classe IOException e, poderemos operar no objeto. Por exemplo, chame printStackTrace() do objeto para imprimir o status atual da pilha. Além disso, também imprimimos o prompt "IO problem" na faixa intermediária.
Independentemente de haver uma exceção ou não, o programa acabará por entrar no bloco final. Fechamos o arquivo no bloco final e limpamos os recursos ocupados pelo descritor de arquivo.
tipo de exceção
Todas as classes de exceção em Java herdam da classe Trowable. Um objeto da classe Throwable pode ser lançado (lançar).
Laranja: desmarcado; azul: marcado;
Os objetos que podem ser arremessados podem ser divididos em dois grupos. Um grupo são exceções não verificadas. Os mecanismos de tratamento de exceções geralmente não são usados para esse grupo de exceções, incluindo:
1. A classe Error geralmente se refere a erros internos e erros do Java, como esgotamento de recursos. Quando ocorre um Erro (e suas derivadas), não podemos resolver o Erro no nível de programação, portanto devemos sair do programa diretamente.
2. A classe Exception possui uma classe derivada especial RuntimeException. RuntimeException (e seus derivados) são causados pelo próprio programa Java, ou seja, devido aos erros do programador durante a programação. RuntimeException pode ser completamente evitado modificando o programa Java. Por exemplo, converter um objeto de um tipo em outro tipo sem relacionamento de herança é uma ClassCastException. Tais anomalias devem e podem ser evitadas.
O resto são exceções verificadas. Essas classes são causadas por interações de programação com o ambiente que causam erros no programa em tempo de execução. Por exemplo, ao ler um arquivo, ocorre uma IOException devido a um erro no próprio arquivo. Outro exemplo é que o servidor de rede altera temporariamente o URL apontando, causando MalformedURLException. O sistema de arquivos e o servidor de rede estão fora do ambiente Java e não estão sob o controle do programador. Se os programadores puderem antecipar exceções, eles poderão usar o mecanismo de tratamento de exceções para desenvolver planos de resposta. Por exemplo, quando há um problema com um arquivo, o administrador do sistema é alertado. Outro exemplo é quando há um problema com o servidor de rede, o usuário é lembrado e aguarda a recuperação do servidor de rede. O mecanismo de tratamento de exceções é usado principalmente para lidar com tais exceções.
lançar uma exceção
No programa acima, a exceção vem de nossa chamada para a API Java IO. Também podemos lançar exceções em nossos próprios programas, como a seguinte classe de bateria, que possui métodos de carregamento e uso:
public class Test{ public static void main(String[] args) { Bateria aBattery = new Battery(); aBattery.useBattery(-0.5); / public void chargeBattery(double p) { // potência <= 1 if (this.power + p < 1.) { this.power = this.power + p; } else { this.power = 1.; /** * consome bateria */ public boolean useBattery(double p) { try { test(p ); out.println("catch Exceção"); System.out.println(e.getMessage()); - p; return true } else { this.power = 0.0; return false } } /** * teste de uso */ private void test(double p) lança Exception // Eu apenas jogo, não manipulo { if ( p < 0) { Exception e = new Exception("p deve ser positivo"); throw e } } private double power = 0,0;
useBattery() indica o uso da operação com bateria. Existe um parâmetro no método useBattery() que indica a quantidade de eletricidade utilizada. Usamos o método test() para testar este parâmetro. Se este parâmetro for negativo, então pensamos que há uma exceção e a lançamos.
No teste, quando ocorre uma exceção (p < 0), criamos um objeto Exception e e usamos uma string como parâmetro. A sequência contém informações relacionadas à exceção e esse parâmetro não é obrigatório. Use throw para lançar o objeto Exception.
Temos manipulador de exceções em useBattery(). Como o método test() não trata diretamente a exceção que gera, mas lança a exceção para o useBattery() superior, precisamos explicar os lançamentos de exceção na definição de test().
(Supondo que o manipulador de exceção não esteja localizado em useBattery(), mas no método main() de nível superior, também precisamos adicionar throws Exception à definição de useBattery().)
No catch, utilizamos o método getMessage() para extrair as informações contidas em sua exceção. Os resultados da execução do programa acima são os seguintes:
catch Exceptionp deve ser positivo
No manipulador de exceções, capturaremos qualquer exceção da classe Exception ou de suas derivadas. Muitas vezes isso não nos ajuda a identificar problemas, especialmente quando um programa pode lançar múltiplas exceções. Podemos fornecer uma classe mais específica para capturar.
Exceção personalizada
Podemos criar novas classes de exceção por meio de herança. Ao herdar, muitas vezes precisamos substituir o construtor. As exceções têm dois construtores, um sem parâmetros e outro com parâmetro String. por exemplo:
class BatteryUsageException estende Exception{ public BatteryUsageException() {} public BatteryUsageException(String msg) { super(msg }});
Podemos fornecer mais métodos e informações relacionadas a exceções em classes derivadas.
Ao personalizar exceções, tome cuidado com a classe base da qual você herda. Uma classe mais específica deve conter mais informações de exceção, como IOException versus Exception.
Resumir
O tratamento de exceções resolve problemas, mas também cria problemas. Em projetos grandes, o tratamento excessivo e detalhado de exceções muitas vezes faz com que o programa se torne uma bagunça. O tratamento de exceções não é simples por natureza e precisa ser usado com cautela.