Le mot anglais anormal est une exception, et la traduction littérale signifie "accident, exception", ce qui signifie des situations anormales. En fait, les exceptions sont essentiellement des erreurs de programme, y compris les erreurs de logique de programme et les erreurs système.
Une préface
Tout le monde connaît la manipulation des exceptions Java, en général, il y a deux points:
1. Jetez l'exception: lancer une exception
class SimpleException {public void a () lève une exception {lancer une nouvelle exception (); };}2. Exceptions de capture:
classe publique MyException {public static void main (String [] args) {myException e = new myException (); SimpleException se = new SimpleException (); essayez {se.a (); } catch (exception e1) {e1.printStackTrace (); }}} classe SimpleException {public void a () lève une exception {throw new exception (); };}Cet article discutera de certains détails sur cette base plus approfondie.
Deux cours d'exception personnalisées
La langue Java nous fournit de nombreuses classes d'exception, mais parfois nous devons encore personnaliser les cours d'exception pour la commodité de l'écriture de code:
class SimpleException étend une exception {};
Après la création, nous pouvons utiliser Try Catch pour le capturer:
classe publique MyException {public static void main (String [] args) {myException e = new myException (); essayez {ea (); } catch (SimpleException e1) {e1.printStackTrace (); }} public void a () lève SimpleException {throw new SimpleException (); }} classe SimpleException étend une exception {};Nous définissons une méthode a () dans MyException, laissez-la lancer une exception SimpleException, puis nous appelons cette méthode dans main () et attrapons cette exception en utilisant Try Catch:
SimpleException sur myException.a (myException.java:15) sur myException.main (myException.java:8) sur sun.reflect.nativemethodaccessorimpcess.invoke0 (méthode native) à sun.reflect.nativemethodaccessorimpl.invoke (nativemethodaccessorimpl.java:57) sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)Process finished with exit code 0
Le résultat après compilation et exécution est principalement basé sur les trois premières lignes. Voici quelques points à expliquer:
1. Spécifiez le type d'exception: (spécification d'exception)
Lorsque nous devons lancer une exception dans une méthode, nous utilisons Throw et ajoutons une instance d'une classe d'exception. Le programme lancera l'exception correspondante au programme client (le programme qui appelle ce code) et quittera ici (équivalent à retourner). Notez également que nous devons spécifier le type d'exception lors de la définition de cette méthode. Par exemple, le code suivant lancera une exception SimpleException
public void a () lève SimpleException
2. Jetez plusieurs exceptions:
public void a () lève SimpleException, aException, bexception {throw new SimpleException (); }Différentes classes d'exception peuvent être séparées par des virgules. Dans ce cas, nous n'avons pas à lancer chaque instance de classe d'exception (), mais le code client doit attraper chaque classe d'exception:
classe publique MyException {public static void main (String [] args) {myException e = new myException (); essayez {ea (); } catch (SimpleException e1) {e1.printStackTrace (); } catch (bexception e1) {e1.printStackTrace (); } catch (aexception e1) {e1.printStackTrace (); }} public void a () lève SimpleException, aException, bexception {throw new SimpleException (); }} classe SimpleException étend une exception {}; class AException étend l'exception {} class Bexception étend une exception {} Trace à trois piles
Qu'il s'agisse de lancer des exceptions ou d'attraper et de gérer des exceptions, notre objectif est d'écrire un programme plus robuste, qui dépend dans une large mesure des informations d'exception fournies par le mécanisme d'exception Java, et son transporteur est la trace de pile.
Dans le code précédent, nous utilisons directement PrintstackTrace () pour imprimer des informations d'exception. En fait, nous pouvons également utiliser la méthode getStackTrace () pour obtenir une collection de stackTraceElement. Si vous avez une idée à portée de main, vous pouvez d'abord rechercher la classe StackTraceElement, et vous pouvez constater qu'il implémente l'interface sérialisable, puis jetez un œil à sa description de classe:
/ ** * Un élément dans une trace de pile, comme renvoyé par {@Link * Throwable # getStackTrace ()}. Chaque élément représente une seule trame de pile. * Toutes les cadres de pile à l'exception de celui en haut de la pile représentent * une invocation de la méthode. Le cadre en haut de la pile représente le * point d'exécution auquel la trace de pile a été générée. En règle générale, * c'est le moment où le jetable correspondant à la trace de pile * a été créé. * * @Since 1.4 * @author Josh Bloch * /Il est clair que chaque instance de cette classe est un élément de la trace de pile, représentant une trame de pile, et la trace de pile est renvoyée par la méthode getStackTrace (). J'ai essayé de traduire plusieurs fois suivant, mais je sentais que ce n'était pas bon, donc je pouvais simplement écrire le code directement pour l'expliquer:
classe publique MyException {public static void main (String [] args) {myException e = new myException (); ea (); public void a () {try {lancer une nouvelle exception (); } catch (exception e) {stackTraceElement [] Ste = e.getStackTrace (); System.out.println (Ste.Length); }}}Nous définissons la méthode A, laissez-la lancer une exception d'exception tout en la capturant, puis nous obtenons un tableau StackTraceElement via la méthode getStackTrace () et imprimez la longueur du tableau:
7
Processus terminé avec le code de sortie 0
Nous avons un peu changé le code et avons cessé d'attraper des exceptions dans un. Nous redéfinissons une méthode B pour qu'elle attrape des exceptions lors de l'appel a:
classe publique MyException {public static void main (String [] args) {myException e = new myException (); eb (); } public void b () {try {a (); } catch (exception e) {stackTraceElement [] Ste = e.getStackTrace (); System.out.println (Ste.Length); }} public void a () lève une exception {throw nouvelle exception (); }}Les résultats sont les suivants:
8
Processus terminé avec le code de sortie 0
Ne vous inquiétez pas, jetons un coup d'œil à quelque chose d'intéressant:
classe publique MyException {public static void main (string [] args) {myException exception = new myException (); essayez {exception.c (); } catch (exception e) {stackTraceElement [] Ste = e.getStackTrace (); System.out.println (Ste.Length); System.out.println ("-----------------------------------------------------------"); for (stackTraceElement s: e.getStackTrace ()) {System.out.println (s.getClassName () + ": Method" + s.getMethodName () + "at line" + s.getlineNumber ()); } System.out.println ("-----------------------------------------------------------"); }} public void c () lève une exception {try {a (); } catch (exception e) {throw e; }} public void a () lève une exception {throw nouvelle exception (); }}Voici les résultats:
8 ----------------------------------------------------------- line57sun.reflect.delegatingMethodAccessOrimpl: Méthode Invoque sur line43java.lang.reflect.method: Méthode Invoke at line606com.intellij.rt.execution.application.appmain: Méthode Main à la ligne144 -------------------------------------------------------
C'est-à-dire que GetStackTrace () renvoie une pile, qui contient des informations de base de l'appelant (main ()) à l'exception initiale de lancer (a ()). Dans le code ci-dessus, nous attrapons l'exception lorsque nous appelons la méthode A dans la méthode C et la jetons à nouveau via des lancers. La méthode appelant la méthode C peut attraper et gérer l'exception, ou vous pouvez choisir de continuer à lancer pour laisser les appelants de niveau supérieur (près du bas de la pile) le gérer. Bien que Rethrow soit très pratique, il y a quelques problèmes. Regardons le code suivant:
classe publique MyException {public static void main (string [] args) {myException exception = new myException (); essayez {exception.c (); } catch (exception e) {e.printStackTrace (System.out); }} public void c () lève une exception {try {a (); } catch (exception e) {throw e; }} public void a () lève une exception {lancer une nouvelle exception ("Exception à partir d'un ()"); }} java.lang.exception: exception de a () sur myException.a (myException.java:40) sur myException.c (myException.java:30) sur myException.main (myException.java:21)Nous remémorons E en C et l'imprimons en utilisant e.printStackTrace () dans Main. Vous pouvez voir que la trace de pile imprimée appartient toujours à a. Si nous voulons transformer la trace de pile en C, nous pouvons l'écrire comme ceci:
classe publique MyException {public static void main (string [] args) {myException exception = new myException (); essayez {exception.c (); } catch (exception e) {e.printStackTrace (System.out); }} public void c () lève une exception {try {a (); } catch (exception e) {// lancer e; lancer (exception) e.fillinstackTrace (); }} public void a () lève une exception {lancer une nouvelle exception ("Exception à partir d'un ()"); }} java.lang.exception: exception de a () sur myException.c (myException.java:22) sur myException.main (myException.java:10) Quatre exceptions chaînage
Jetons un coup d'œil à un scénario:
classe publique TestException {public static void main (String [] args) {TestException TestException = new TestException (); essayez {testException.c (); } catch (cexception e) {e.printStackTrace (); }} public void a () lève aException {aException aException = new AException ("Ceci est une exception"); jeter une aexception; } public void b () lève bexception {try {a (); } catch (aexception e) {lance une nouvelle bexception ("Ceci est B Exception"); }} public void c () lève cexception {try {b (); } catch (bexception e) {throw new Cexception ("This is C exception"); }}} class AException étend une exception {public aexception (String msg) {super (msg); }} classe bexception étend une exception {public bexception (String msg) {super (msg); }} class CException étend une exception {public cexception (String msg) {super (msg); }}Trois classes d'exception aexception, bexception et cexception sont créées, puis aexception est lancé dans un (), l'aexception est capturée dans b () et la bexception est lancée, et finalement la bexception est prise en c () et la cexception est lancée, et le résultat est imprimé comme suit:
Cexception: Ceci est C exception sur TestException.c (TestException.java:31) sur TestException.Main (TestException.java:8)
Ok, nous ne voyons que les informations de Cexception, AEXCECTION et BException ont été perdues, et la fonction de la chaîne d'exception sortira, voir le code:
classe publique TestException {public static void main (String [] args) {TestException TestException = new TestException (); essayez {testException.c (); } catch (cexception e) {e.printStackTrace (); }} public void a () lève aException {aException aException = new AException ("Ceci est une exception"); jeter une aexception; } public void b () lève bexception {try {a (); } catch (aexception e) {// lance une nouvelle bexception ("This is B exception"); Bexception bexception = new bexception ("This is B exception"); bexception.initcause (e); jeter une bexception; }} public void c () lève cexception {try {b (); } catch (bexception e) {// lancer une nouvelle cexception ("This is C exception"); Cexception cexception = new cexception ("This is C exception C"); cexception.initcause (e); jeter la cexception; }}} class AException étend une exception {public aexception (String msg) {super (msg); }} classe bexception étend une exception {public bexception (String msg) {super (msg); }} class CException étend une exception {public cexception (String msg) {super (msg); }}Nous utilisons la méthode initcause () pour connecter les informations d'exception, et le résultat est le suivant:
Cexception: Ceci est une exception C sur TestException.C (TestException.Java:35) sur TestException.Main (TestException.Java:8) à Sun.Reflect.NativeMethodAccessOrimpressorimpt.Invoke (NativeMethodAccessorImpl.Java:57) Sun.Reflect.delegatingMethodAccessOrimpl.invoke (délégation deMethodAccessorimp.java:43) à java.lang.reflect.method.invoke (méthode.java:606) à com.intellij.rt.execution.application.appmain.main (appmain.java:144) est une exception B sur TestException.B (TestException.Java:24) sur TestException.C (TestException.java:32) ... 6 MoreCaused by: aException: Ceci est une exception sur TestException.A (TestException.Java:15) à TestException.B (TestException.java:21) ... 7 More Process terminé avec Exit Code 0 0
Les cinq postscript
En fait, il y a encore beaucoup de choses à discuter de la manipulation des exceptions Java, mais parce que j'ai une expérience limitée, je ne peux pas le comprendre trop profondément, et le plus couramment utilisé est
Essayez {...} catch (exception e) {...} Enfin {// code qui sera exécuté, que l'exception soit capturée ou traitée, telle que la fermeture des opérations IO}Mais quoi qu'il en soit, nous devons encore remercier Java de nous avoir fourni le mécanisme d'exception. C'est comme un aîné, nous guidant de temps en temps et nous faisant moins ennuyés lors de l'encodage :)