A palavra inglesa anormal é exceção e a tradução literal significa "acidente, exceção", o que significa situações anormais. De fato, exceções são essencialmente erros de programa, incluindo erros de lógica do programa e erros do sistema.
Um prefácio
Todo mundo está familiarizado com o manuseio de exceções de Java, em geral, há dois pontos:
1. Exceção de arremesso: Exceção de arremesso
classe SimpleException {public void a () lança exceção {tiro nova exceção (); };}2. Exceções de capture:
public class MyException {public static void main (string [] args) {myException e = new MyException (); SimpleException SE = new SimpleException (); tente {SE.A (); } catch (Exceção E1) {e1.printStackTrace (); }}} classe SimpleException {public void a () lança exceção {lança nova exceção (); };}Este artigo discutirá alguns detalhes sobre isso mais aprofundado.
Duas aula de exceção personalizada
A linguagem Java nos fornece muitas aulas de exceção, mas às vezes ainda precisamos personalizar as classes de exceção para a conveniência de escrever código:
classe SimpleException estende a exceção {};
Após a criação, podemos usar o Experting Catch para capturá -lo:
public class MyException {public static void main (string [] args) {myException e = new MyException (); tente {ea (); } catch (SimpleException E1) {e1.printStackTrace (); }} public void a () lança SimpleException {throw new SimpleException (); }} classe SimpleException estende a exceção {};Definimos um método a () na MyException, que ele faça uma exceção do SimpleException, então chamamos esse método em main () e pegamos essa exceção usando o Try Catch:
SimpleException em myException.a (myException.java:15) em myexception.main (myException.java:8) em sun.reflect.nativeMethodaccessorImpl.inVoke0 (método nativo) em sun.reflelect.nativeMethodaccLeacplEmpl.inVoke (nativeModAnchenchenchenchencheClactEngModEss.Afless.nativeMethodAccessorImpl.inVoke (nativeModAnchenchencheCles. sun.Reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43) em java.lang.reflect.method.invoke (method.java:606) em com.intellij.mtt.execution.pplication.Apcmain.ApcMain.Apcmain.Apmin.MainMain.
O resultado após a compilação e a execução é baseado principalmente nas três primeiras linhas. Aqui estão alguns pontos a serem explicados:
1. Especifique o tipo de exceção: (especificação de exceção)
Quando precisamos lançar uma exceção em um método, usamos o Throw e adicionamos uma instância de uma classe de exceção. O programa lançará a exceção correspondente ao programa do cliente (o programa que chama esse código) e sairá aqui (equivalente ao retorno). Observe também que devemos especificar o tipo de exceção ao definir esse método. Por exemplo, o código a seguir lançará uma exceção do SimpleException
public void a () lança SimpleException
2. Jogue várias exceções:
public void a () lança SimpleException, AException, Bexception {throw New SimpleException (); }Diferentes classes de exceção podem ser separadas por vírgulas. Nesse caso, não precisamos lançar cada instância da classe de exceção (), mas o código do cliente deve pegar cada classe de exceção:
public class MyException {public static void main (string [] args) {myException e = new MyException (); tente {ea (); } catch (SimpleException E1) {e1.printStackTrace (); } catch (bexception e1) {e1.printStackTrace (); } catch (aException e1) {e1.printStackTrace (); }} public void a () lança SimpleException, AException, Bexception {throw new SimpleException (); }} classe SimpleException estende a exceção {}; classe aException estende a exceção {} classe bexception estende a exceção {} Três rastreamentos de pilha
Seja lançando exceções ou exceções de captura e manipulação, nosso objetivo é escrever um programa mais robusto, que depende em grande parte das informações de exceção fornecidas pelo mecanismo de exceção do Java, e sua transportadora é o rastreamento da pilha.
No código anterior, usamos diretamente o PrintStackTrace () para imprimir informações de exceção. De fato, também podemos usar o método getStackTrace () para obter uma coleção de StacktraceElement. Se você tiver idéia em mãos, primeiro procure a aula de StackTraceElement e pode descobrir que ela implementa a interface serializável e depois dê uma olhada na descrição da classe:
/** * Um elemento em um rastreamento de pilha, conforme retornado por {@link * throwable#getStackTrace ()}. Cada elemento representa uma única estrutura de pilha. * Todos os quadros de pilha, exceto o da parte superior da pilha, representam * uma invocação de método. O quadro na parte superior da pilha representa o * ponto de execução no qual o rastreamento da pilha foi gerado. Normalmente, * este é o ponto em que o jogável correspondente ao rastreamento da pilha * foi criado. * * @since 1.4 * @Author Josh Bloch */É claro que cada instância desta classe é um elemento do rastreamento da pilha, representando um quadro de pilha, e o rastreamento da pilha é retornado pelo método getStackTrace (). Tentei traduzir as seguintes várias vezes, mas achei que não era bom, então eu poderia apenas escrever o código diretamente para explicar:
public class MyException {public static void main (string [] args) {myException e = new MyException (); ea (); public void a () {tente {lança nova exceção (); } Catch (Exceção e) {StackTraceElement [] ste = e.getStackTrace (); System.out.println (ste.length); }}}Definimos o método A, vamos fazer uma exceção de exceção ao captá -lo e, em seguida, obtemos uma matriz de StacktraceElement através do método getStackTrace () e imprimimos o comprimento da matriz:
7
Processo terminado com o código de saída 0
Mudamos um pouco o código e paramos de pegar exceções em a. Redefinimos um método B para que ele pegue exceções enquanto liga para:
public class MyException {public static void main (string [] args) {myException e = new MyException (); eb (); } public void b () {tente {a (); } Catch (Exceção e) {StackTraceElement [] ste = e.getStackTrace (); System.out.println (ste.length); }} public void a () lança Exceção {lança nova exceção (); }}Os resultados são os seguintes:
8
Processo terminado com o código de saída 0
Não se preocupe, vamos dar uma olhada em algo interessante:
public class MyException {public static void main (string [] args) {MyException Exception = new MyException (); tente {excepcion.c (); } Catch (Exceção e) {StackTraceElement [] ste = e.getStackTrace (); System.out.println (ste.length); System.out.println ("-------------------------------------------------------------"); para (StackTraceElement s: e.getStackTrace ()) {System.out.println (s.getClassName ()+": métodos"+s.getMethodName ()+"na linha"+s.getLinEnMumber ()); } System.out.println ("-----------------------------------------------------------------"); }} public void c () lança a exceção {try {a (); } catch (Exceção e) {tiro e; }} public void a () lança Exceção {lança nova exceção (); }}Aqui estão os resultados:
8 --------------------------------------------------------- line57sun.reflelect.delegatingMethodAccessorImpl: Método Invoke em line43java.lang.reflect.method: Método Invoke em line606com.Intellij.rt.execution.application.appmain: Método Principal em Linha144 -----------------------------------
Ou seja, o getStackTrace () retorna uma pilha, que contém algumas informações básicas do chamador (main ()) à exceção inicial de arremesso (a ()). No código acima, pegamos a exceção ao chamar o método A no método C e lançá -lo novamente através de lances. O método que chama o método C pode capturar e lidar com a exceção, ou você pode optar por continuar jogando para permitir que os chamadores de nível superior (perto da parte inferior da pilha) lidam com ela. Embora Rethrow seja muito conveniente, existem alguns problemas. Vejamos o seguinte código:
public class MyException {public static void main (string [] args) {MyException Exception = new MyException (); tente {excepcion.c (); } catch (Exceção e) {e.printStackTrace (System.out); }} public void c () lança a exceção {try {a (); } catch (Exceção e) {tiro e; }} public void a () lança Exceção {THROW NOVA Exceção ("Exceção de A ()"); }} java.lang.Exception: Exceção de um () em myexception.a (myException.java:40) em myexception.c (myexception.java:30) em myexception.main (myexception.java:21)Nós novamente abrigamos E em C e o imprimimos usando o E.PrintStackTrace () em Main. Você pode ver que o rastreamento da pilha impressa ainda pertence a a. Se quisermos transformar o rastreamento da pilha em C, podemos escrever assim:
public class MyException {public static void main (string [] args) {MyException Exception = new MyException (); tente {excepcion.c (); } catch (Exceção e) {e.printStackTrace (System.out); }} public void c () lança a exceção {try {a (); } catch (Exceção e) {// tiro e; arremesso (exceção) e.fillinstacktrace (); }} public void a () lança Exceção {THROW NOVA Exceção ("Exceção de A ()"); }} java.lang.Exception: Exceção de um () em myexception.c (myException.java:22) em myexception.main (myException.java:10) Quatro encadeamento de exceção
Vamos dar uma olhada em um cenário:
classe pública testException {public static void main (string [] args) {testException testException = new testException (); tente {testException.c (); } catch (cException e) {e.printStackTrace (); }} public void a () lança aException {aException Aexception = new Aexception ("Esta é uma exceção"); jogar aexception; } public void b () lança bexception {try {a (); } catch (aexception e) {tiro a nova bexception ("Esta é a exceção B"); }} public void c () lança cException {try {b (); } catch (bexception e) {lança nova cException ("Esta é a exceção c"); }}} classe aException estende a exceção {public aexception (string msg) {super (msg); }} classe Bexception estende a exceção {public bexception (string msg) {super (msg); }} classe CException estende a exceção {public cException (string msg) {super (msg); }}Três classes de exceção Aexception, Bexception e cException são criadas, então a AException é lançada em uma (), aexception é capturada em B () e a Bexception é lançada e, finalmente, a Bexception é capturada em c () e a cException é lançada e o resultado é impresso da seguinte maneira:
CException: Esta é a exceção c em testexception.c (testexception.java:31) em testexception.main (testexception.java:8)
OK, só vemos as informações da CEXCECTION, AEXCECPEIRA e BEXCECCECTION foram perdidas, e a função da cadeia de exceção será lançada, veja o código:
classe pública testException {public static void main (string [] args) {testException testException = new testException (); tente {testException.c (); } catch (cException e) {e.printStackTrace (); }} public void a () lança aException {aException Aexception = new Aexception ("Esta é uma exceção"); jogar aexception; } public void b () lança bexception {try {a (); } catch (aException e) {// lança a nova bexception ("Esta é a exceção B"); Bexception bexception = new bexception ("Esta é a exceção b"); bexception.initcause (e); lançar bexception; }} public void c () lança cException {try {b (); } catch (bexception e) {// lança nova cException ("Esta é a exceção c"); CException cException = nova cException ("Esta é a exceção c"); cException.Initcause (e); lançar cException; }}} classe aException estende a exceção {public aexception (string msg) {super (msg); }} classe Bexception estende a exceção {public bexception (string msg) {super (msg); }} classe CException estende a exceção {public cException (string msg) {super (msg); }}Utilizamos o método initCause () para conectar as informações de exceção, e o resultado é o seguinte:
CException: Esta é a exceção c em testException.c (testException.java:35) em testException.main (testException.java:8) em sun.reflelect.nativethodaccessoriMpl.invoke0 (método nativo) em sun.refLECT.nativeMetodAccAncessorImpl.Invoke (Native) at Sun.reflect.nativeMetodAcaccArmPl.invoke (nivoke) em sun. sun.Reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43) em java.lang.reflect.method.invoke (method.java:606) em com.intellij.mtt.execution.pplication.Apcmain.AppMain.ApminM.MainMain.matur.mation.patrain.patain.matur.matur.mation.patrain.patrain.patrain. é b exceção no testException.b (testException.java:24) em testexception.c (testexception.java:32) ... 6 Morecaused by: Aexception: esta é uma exceção no testException.a (testException.java:15) no testException.b (exexception.java:21) ... 7 mais.
Os cinco pós -escritos
De fato, ainda há muitas coisas para discutir sobre o manuseio de exceções de Java, mas porque tenho experiência limitada, não consigo entender muito profundamente, e o mais comumente usado é
tente {...} catch (Exceção e) {...} finalmente {// código que será executado independentemente de a exceção será capturada ou processada, como o fechamento de operações de IO}Mas não importa o quê, ainda temos que agradecer a Java por nos fornecer o mecanismo de exceção. É como um ancião, nos guiando de tempos em tempos e nos tornando menos entediados ao codificar :)