 |
 |
10) Gestion des erreurs avec les exceptions |
|
 |
|
Texte original |
 |
Traducteur : N. CULWELL-KANAREK, Anthony PRAUD, A. FORTUN |
|
 |
|
Ce chapitre contient 3 pages
1
2
3
|
|
|
 |
 |
 |
 |
 |
 |
|
 |
2004.02.05 - version 0.3 : - Fin de la correction du chapitre. Refait la partie traduite par papashultz, trop mauvaise (genre logiciel de traduction automatique). - Repassage au correcteur d'orth d'openoffice. 2003.06.24 - Version 0.2 : - Mise en forme du code html (titres-hx[verdana], paragraphes-p[Georgia], code-blockquote); - Premier passage rapide au correcteur Orth (Starffice5.2). 2003.04.18 - Version 0.1 : - Première version, traduction non terminée. Traducteur : - Anthony PRAUD Texte original : -Thinking in Java, 2nd edition, Revision 10 © 2000 by Bruce Eckel
|
 |
 |
 |
10: Error Handling with Exceptions
|
 |
Gestion des erreurs avec les exceptions
|
 |
 |
 |
The basic philosophy of Java is
that “badly formed code will not be run.”
|
 |
La philosophie de base de Java est que
« un code mal formé ne sera pas exécuté ».
|
 |
 |
 |
The ideal time to catch an
error is at compile-time, before
you even try to run the program. However, not all errors can be detected at
compile-time. The rest of the problems must be handled at run-time, through some
formality that allows the originator of the error to pass appropriate
information to a recipient who will know how to handle the difficulty
properly.
|
 |
L'instant idéal pour détecter une erreur est la
compilation, bien avant que vous essayiez d'exécuter le
programme. Malheureusement, toutes les erreurs ne peuvent
être détectées à cette étape. Les problèmes restants doivent être
gérés à l'exécution avec un certain formalisme qui permet à
l'initiateur de l'erreur de passer une information suffisante à un
récepteur qui va savoir comment traiter proprement cette
anomalie.
|
 |
 |
 |
In C and other earlier languages, there
could be several of these formalities, and they were generally established by
convention and not as part of the programming language. Typically, you returned
a special value or set a flag, and the recipient was supposed to look at the
value or the flag and determine that something was amiss. However, as the years
passed, it was discovered that programmers who use a library tend to think of
themselves as invincible—as in, “Yes, errors might happen to others,
but not in my code.” So, not too surprisingly, they wouldn’t
check for the error conditions (and sometimes the error conditions were too
silly to check
for[51]). If you
were thorough enough to check for an error every time you called a
method, your code could turn into an unreadable nightmare. Because programmers
could still coax systems out of these languages they were resistant to admitting
the truth: This approach to handling errors was a major limitation to creating
large, robust, maintainable programs.
|
 |
En C et dans d'autres langages plus anciens, il
pouvait y avoir plusieurs formalismes, et ils étaient généralement
établis comme des conventions et pas comme partie intégrante du
langage de programmation. la gestion des erreurs se faisant
typiquement en retournant par exemple une valeur spécifique ou en
positionnant un drapeau [flag], le récepteur avait la charge de tester
ces données et de déterminer qu'il y avait eu une anomalie. Malgré
cela au fil des ans on se rendit compte que les programmeurs qui
utilisent des librairies avaient tendance à se croire infaillible «
oui des erreurs peuvent se produire chez les autres mais pas dans
mon code ! » Alors, de façon quasi naturelle, ils ne
souhaitaient pas tester les conditions d'erreur (elles étaient parfois
trop grossières pour être testées [51].
Si vous étiez assez méticuleux pour tester
toutes les conditions d'erreur à chaque appel de fonction votre code
pouvait devenir d'une illisibilité cauchemardesque. Parce que les
programmeurs avaient toujours la possibilité de coupler un système
avec ces langages ils étaient réticents à admettre la vérité : cette
approche de la gestion des erreurs était un obstacle à la
création de grands programmes, robustes et faciles à maintenir.
|
 |
 |
 |
The solution is to take the casual nature
out of error handling and to enforce formality. This actually has a long
history, since implementations of exception handling go back to operating
systems in the 1960s, and even to BASIC’s “on error
goto.” But C++ exception handling was based on Ada, and Java’s
is based primarily on C++ (although it looks even more like Object
Pascal).
|
 |
La solution est prendre la nature primitive de la
gestion des erreurs et de renforcer le formalisme. Cette solution à
une longue histoire, puisque l'implémentation de la gestion des
erreurs remonte au systèmes d'exploitation des années soixante et
même au « ON ERROR GOTO » du BASIC. Mais la gestion des erreurs
du C++ était basée sur ADA, et Java est basé sur le C++ (bien qu'il
ressemble plus a du pascal objet).
|
 |
 |
 |
The word “exception” is meant
in the sense of “I take exception to that.” At the point where the
problem occurs you might not know what to do with it, but you do know that you
can’t just continue on merrily; you must stop and somebody, somewhere,
must figure out what to do. But you don’t have enough information in the
current context to fix the problem. So you hand the problem out to a higher
context where someone is qualified to make the proper decision (much like a
chain of command).
|
 |
Le « Mot » exception est pris dans le sens « je
fais exception de ce cas ». A l'instant ou le problème se produit vous
pouvez ne pas savoir quoi en faire mais vous savez que vous ne pouvez
pas continuer sans vous en soucier ; vous devez vous arrêter et
quelqu'un quelque part doit savoir que faire. Donc vous transmettez le
problème dans un contexte plus général ou quelqu'un est qualifié pour
prendre la décision appropriée (comme dans une chaîne de
commandement).
|
 |
 |
 |
The other rather significant benefit of
exceptions is that they clean up error handling code. Instead of checking for a
particular error and dealing with it at multiple places in your program, you no
longer need to check at the point of the method call (since the exception will
guarantee that someone catches it). And, you need to handle the problem in only
one place, the so-called exception handler. This
saves you code, and it separates the code that describes what you want to do
from the code that is executed when things go awry. In general, reading,
writing, and debugging code becomes much clearer with exceptions than when using
the old way of error handling.
|
 |
l'autre apport significatif de la gestion des
exceptions est qu'elle simplifie le code de la gestion des erreurs. Au
lieu de tester une condition d'erreur et la traiter à différents
endroits de votre programme, vous n'avez plus besoin de placer le code
de gestion des erreurs à l'appel de la méthode (puisque l'exception
garantira que quelqu'un la lèvera) et vous avez juste besoin de
traiter le problème à un seul endroit, appelé Exception
Handler. Cette gestion vous permet d'économiser du code, et de
séparer le code que vous voulez exécuter du code qui doit être exécuté
quand des erreurs se produisent. Généralement, la lecture l'écriture
et le déboguage du code est plus claire avec les exceptions qu'avec
l'ancienne méthode.
|
 |
 |
 |
Because exception handling is enforced by
the Java compiler, there are only so many examples that can be written in this
book without learning about exception handling. This chapter introduces you to
the code you need to write to properly handle exceptions, and the way you can
generate your own exceptions if one of your methods gets into
trouble.
|
 |
La gestion des exceptions étant supportée par le
Compilateur JAVA, il y a de nombreux exemples qui peuvent être écrits
dans ce livre sans apprendre le mécanisme de gestion des exceptions.
Ce chapitre vous instruit sur le code dont vous avez besoin pour gérer
de façon adéquate les exceptions, et la façon de générer vos propres
exceptions si une de vos méthodes venait à ne pas fonctionner.
|
 |
 |
 |
Basic exceptions
|
 |
Les exceptions de base
|
 |
 |
 |
An exceptional
condition is a problem that prevents the continuation of the method or scope
that you’re in. It’s important to distinguish an exceptional
condition from a normal problem, in which you have enough information in the
current context to somehow cope with the difficulty. With an exceptional
condition, you cannot continue processing because you don’t have the
information necessary to deal with the problem in the current context.
All you can do is jump out of the current context and relegate that problem to a
higher context. This is what happens when you throw an
exception.
|
 |
Une condition exceptionnelle est un
problème qui interdit de continuer la méthode ou la partie de code que
vous êtes en train d'exécuter. il est important de distinguer une
condition exceptionnelle d'un problème normal. Avec une condition
exceptionnelle vous ne pouvez pas continuer l'exécution car vous
n'avez pas suffisamment d'informations pour la traiter dans le
contexte courant. Tout ce que vous pouvez faire est de changer
de contexte et d'essayer de régler ce problème dans un contexte de
plus haut niveau. C'est ce qui se passe quand vous générez une
exception.
|
 |
 |
 |
A simple example is a divide. If
you’re about to divide by zero, it’s worth checking to make sure you
don’t go ahead and perform the divide. But what does it mean that the
denominator is zero? Maybe you know, in the context of the problem you’re
trying to solve in that particular method, how to deal with a zero denominator.
But if it’s an unexpected value, you can’t deal with it and so must
throw an exception rather than continuing along that path.
|
 |
Un exemple simple est la division. Si vous vous
apprêtez à diviser par Zéro, il est intéressant de vérifier que le
dénominateur est non nul avant d'effectuer la division. Mais qu'est ce
que cela signifie que le dénominateur soit égal à zéro ? Peut être
savez vous, dans le contexte, de cette méthode particulière comment
agir avec un dénominateur égal à Zéro. Mais si c'est une valeur
inattendue, vous ne pouvez pas la traiter et vous devez donc générer
une exception plutôt que de continuer l'exécution.
|
 |
 |
 |
When you throw an
exception, several things happen. First, the exception
object is created in the same way that any Java object is created: on the heap,
with new. Then the current path of execution (the one you couldn’t
continue) is stopped and the reference for the exception object is ejected from
the current context. At this point the exception handling mechanism takes over
and begins to look for an appropriate place to continue executing the program.
This appropriate place is the exception handler, whose job is to recover
from the problem so the program can either try another tack or just
continue.
|
 |
Quand vous générez une exception, plusieurs
actions sont déclenchées. Premièrement, l'objet Exception est
instancié de la même façon que tout objet java est crée : à la volée
avec l'instruction new. Ensuite le chemin courant d'exécution
(celui que vous ne pouvez continuer) est stoppé et la référence à
l'objet exception est sortie du contexte courant. A cet instant le
mécanisme des gestion des exceptions prend la main et commence à
chercher un endroit approprié pour continuer à exécuter le programme.
Cet endroit est le Gestionnaire d'exception (Exception
Handler), dont la tâche est de résoudre le problème de façon à ce que
le programme puisse essayer de lancer ou une autre tâche ou juste
continuer en séquence.
|
 |
 |
 |
As a simple example of throwing an
exception, consider an object reference called t. It’s possible
that you might be passed a reference that hasn’t been initialized, so you
might want to check before trying to call a method using that object reference.
You can send information about the error into a larger context by creating an
object representing your information and “throwing” it out of your
current context. This is called throwing an exception. Here’s what
it looks like:
|
 |
Pour prendre un exemple simple, considérons une
instance d'objet appelée t. Il est possible qu'il vous soit
passé une référence qui n'ai pas été initialisée, donc vous pouvez
vouloir vérifier son initialisation avant d'appeler une méthode sur
cette instance. Vous pouvez envoyer l'information sur l'erreur dans un
contexte plus général en créant un objet représentant votre
information et en la lançant depuis votre contexte. Cette action
s'appelle générer une exception. Cette action ressemble à ceci
:
|
 |
 |
 |
if(t == null) throw new NullPointerException();
|
 |
if(t == "#0000FF">null) throw "#0000FF">new NullPointerException();
|
 |
 |
 |
This throws the exception, which allows
you—in the current context—to abdicate responsibility for thinking
about the issue further. It’s just magically handled somewhere else.
Precisely where will be shown
shortly.
|
 |
Ce code génère l'exception ,ce qui vous permet de
vous décharger de la responsabilité de penser à ce problème pour le
moment. C'est juste par magie traité autre part. Nous verrons,
succinctement, où cela se passe.
|
 |
 |
 |
Exception arguments
|
 |
Les paramètres des Exceptions
|
 |
 |
 |
Like any object in Java, you always
create exceptions on the heap using new, which allocates storage and
calls a constructor. There are two constructors in all standard exceptions: the
first is the default constructor, and the second takes a string argument so you
can place pertinent information in the exception:
|
 |
Comme pour tout objet en Java, vous créez des
exceptions dans la pile [Heap] en utilisant new, qui alloue de
l'espace mémoire et appelle un constructeur. Il y a deux constructeurs
dans toutes les exceptions standards : le premier est le constructeur
par défaut et le second prend une chaîne de caractères comme argument
ainsi vous pouvez placer des informations pertinentes dans l'exception
:
|
 |
 |
 |
if(t == null) throw new NullPointerException("t = null");
|
 |
if(t == "#0000FF">null) throw "#0000FF">new NullPointerException("#004488">"t = null");
|
 |
 |
 |
This string can later be extracted using
various methods, as will be shown shortly.
|
 |
Cette chaîne de caractères peut être extraite ultérieurement de
différentes façons, nous verrons cela brièvement.
|
 |
 |
 |
The keyword
throw causes a number of relatively magical things to happen. Typically,
you’ll first use new to create an object that represents the
error condition. You give the resulting reference to throw. The object
is, in effect, “returned” from the method, even though that object
type isn’t normally what the method is designed to return. A simplistic
way to think about exception handling is as an alternate return mechanism,
although you get into trouble if you take that analogy too far. You can also
exit from ordinary scopes by throwing an exception. But a value is returned, and
the method or scope exits.
|
 |
Le mot-clé throw déclenche une série d'événements relativement
magiques. Typiquement, vous allez d'abord utilisez new pour
instancier un objet qui représente la condition d'erreur. Vous
transmettez la référence résultante au throw. L'objet est en effet retourné par la méthode, même si ce n'est pas ce
type d'objet que la méthode doit renvoyer. Une vision simpliste de la
gestion des exceptions est de la considérer comme un mécanisme de
retour mais vous allez au devant de problèmes si vous poursuivez cette
analogie trop loin. Vous pouvez aussi sortir de l'exécution normale en
lançant une exception. Mais une valeur est retournée et la méthode ou
l'environnement se termine.
|
 |
 |
 |
Any similarity to an ordinary return from
a method ends here, because where you return is someplace completely
different from where you return for a normal method call. (You end up in an
appropriate exception handler that might be miles away—many levels lower
on the call stack—from where the exception was thrown.)
|
 |
Toute similitude avec un retour ordinaire d'une méthode s'arrête ici
parce que l'endroit où vous arrivez est complètement différent
de celui d'un retour normal d'une méthode. (Vous atterrissez chez le
gestionnaire d'exception approprié qui peut être très éloigné,
plusieurs niveau plus bas sur la pile d'appels, de l'endroit ou
l'exception a été générée.)
|
 |
 |
 |
In addition, you can throw any type of
Throwable object that you want. Typically, you’ll throw a different
class of exception for each different type of error. The information about the
error is represented both inside the exception object and implicitly in the type
of exception object chosen, so someone in the bigger context can figure out what
to do with your exception. (Often, the only information is the type of exception
object, and nothing meaningful is stored within the exception
object.)
|
 |
De plus, vous pouvez lancer n'importe quel type d'objet
Throwable. Ainsi vous générerez une classe d'exception pour
chaque type d'erreur. l'information à propos de l'erreur est contenue
à la fois dans l'objet exception et implicitement dans le type de
l'objet exception choisi, afin que quelqu'un dans le contexte
supérieur sache quoi faire de votre exception (Souvent, la seule
information est le type de l'objet exception rien d'autre de
significatif est stocké.)
|
 |
 |
 |
Catching an exception
|
 |
Attraper une exception
|
 |
 |
 |
If a method throws an exception, it must
assume that exception is “caught” and dealt with. One of the
advantages of Java exception handling is that it allows you to concentrate on
the problem you’re trying to solve in one place, and then deal with the
errors from that code in another place.
|
 |
Si une méthode génère une exception elle doit supposer qu'elle sera
intercepté et levée. Un des avantages de la gestion des exceptions
dans Java est qu'elle vous permet de vous concentrer sur le problème
que vous essayez de résoudre à un endroit, et enfin de placer le code
concernant les erreurs à un autre endroit.
|
 |
 |
 |
To see how an exception is caught, you
must first understand the concept of a
guarded region, which is
a section of code that might produce exceptions, and which is followed by the
code to handle those
exceptions.
|
 |
Pour comprendre comment une exception est levée vous devez comprendre
le concept de région surveillée qui est une région de code qui
peut générer des exceptions et qui est suivie par le code qui traite
ces exceptions.
|
 |
 |
 |
The try block
|
 |
Le bloc try
|
 |
 |
 |
If you’re inside a method and you
throw an exception (or another method you call within this method throws an
exception), that method will exit in the process of throwing. If you don’t
want a throw to exit the method, you can set up a special block within
that method to capture the exception. This is called the try
block because you
“try” your various method calls there. The try block is an ordinary
scope, preceded by the keyword try:
|
 |
Si vous êtes à l'intérieur d'une méthode et que vous générez une
exception (ou une méthode à l'intérieur de celle ci génère une
exception), cette méthode va sortir dans le processus de génération de
l'exception. Si vous ne voulez pas qu'un throw provoque la
sortie de la méthode vous pouvez spécifier un bloc spécial à
l'intérieur de celle-ci qui va intercepter l'exception. C'est le Bloc
try appelé ainsi car vous essayez vos différents appels de
méthode ici . Le bloc try est une section ordinaire précédé du
mot clé try.
|
 |
 |
 |
try { // Code that might generate exceptions }
|
 |
try { // Code that might generate exceptions }
|
 |
 |
 |
If you were checking for errors carefully
in a programming language that didn’t support exception handling,
you’d have to surround every method call with setup and error testing
code, even if you call the same method several times. With exception handling,
you put everything in a try block and capture all the exceptions in one place.
This means your code is a lot easier to write and easier to read because the
goal of the code is not confused with the error
checking.
|
 |
Si vous vouliez tester les erreurs attentivement dans un langage de
programmation qui ne supporte pas la gestion des exceptions vous
devriez entourez l'appel de chaque méthode avec le code de
vérification de l'initialisation et de vérification des erreurs, même
si vous appeliez la même méthode plusieurs fois. Avec la Gestion des
exceptions vous mettez tout dans le bloc try et capturer toute les
exceptions en un seul endroit. Cela signifie que votre code est
beaucoup plus simple à lire et à écrire car le bon code est séparé de
celui de la gestion des erreurs.
|
 |
 |
 |
Exception handlers
|
 |
Les gestionnaires d'exceptions
|
 |
 |
 |
Of course, the thrown exception must end
up someplace. This “place” is the exception
handler, and there’s
one for every exception type you want to catch. Exception handlers immediately
follow the try block and are denoted by the keyword
catch:
|
 |
Bien sûr, l'exception générée doit être traitée quelque part. Cet
endroit est le gestionnaire d'exceptions, et il y en a un pour
chaque type d'exception que vous voulez intercepter. Les gestionnaires
d'exceptions sont placés juste derrière le bloc try. Et
reconnaissables par le mot clé catch.
|
 |
 |
 |
try { // Code that might generate exceptions } catch(Type1 id1) { // Handle exceptions of Type1 } catch(Type2 id2) { // Handle exceptions of Type2 } catch(Type3 id3) { // Handle exceptions of Type3 }
// etc...
|
 |
try { // Code that might generate exceptions } catch(Type1 id1) { // Handle exceptions of Type1 } catch(Type2 id2) { // Handle exceptions of Type2 } catch(Type3 id3) { // Handle exceptions of Type3 } // etc...
|
 |
 |
 |
Each catch clause (exception handler) is
like a little method that takes one and only one argument of a particular type.
The identifier (id1, id2, and so on) can be used inside the
handler, just like a method argument. Sometimes you never use the identifier
because the type of the exception gives you enough information to deal with the
exception, but the identifier must still be there.
|
 |
Chaque clause du catch (gestionnaire d'exception) est comme une
méthode qui ne prend qu'un argument d'un type particulier. Les
identifiants (id1,id2, et ainsi de suite) peuvent êtres
utilisés dans les gestionnaire d'exception, comme des paramètres de
méthodes. Quelque fois vous n'utilisez pas l'identifiant car le type
de l'exception vous fournit assez d'informations pour la traiter mais
il doit toujours être présent.
|
 |
 |
 |
The handlers must appear directly after
the try block. If an exception is thrown, the exception handling mechanism goes
hunting for the first handler with an argument that matches the type of the
exception. Then it enters that catch clause, and the exception is considered
handled. The search for handlers stops once the catch clause is finished. Only
the matching catch clause executes; it’s not like a switch
statement in which you need a break after each case to prevent the
remaining ones from executing.
|
 |
Le gestionnaire doit être placé juste derrière le bloc try. Si une
exception est générée, le mécanisme de gestion des exceptions va à la
recherche du premier gestionnaire d .exception dont le type correspond
à celui de l'exception, cette recherche se termine quand une des
clauses Catch est exécutée. Seulement une clause catch sera exécutée ;
ce n'est pas comme un switch ou vous devez positionner un break
après chaque case pour empêcher les autres conditions de
s'exécuter.
|
 |
 |
 |
Note that, within the try block, a number
of different method calls might generate the same exception, but you need only
one handler.
|
 |
Prenez note qu'avec le bloc try, différentes méthodes peuvent générer
la même exception mais vous n'aurez besoin que d'un seul gestionnaire
d'exception.
|
 |
 |
 |
Termination vs.
resumption
|
 |
Terminaison contre Restauration
|
 |
 |
 |
There are two basic models in exception
handling theory. In termination (which is what Java and C++ support), you
assume the error is so critical that there’s no way to get back to where
the exception occurred. Whoever threw the exception decided that there was no
way to salvage the situation, and they don’t want to come
back.
|
 |
Ce sont les deux modèles de base dans la théorie de la gestion des
exceptions. Dans la terminaison (supportée par Java et C++) on
suppose que l'erreur est si critique qu'il n'est pas possible de
recommencer l'exécution à partir de l'endroit ou c'est produit
l'exception. Celui qui génère l'exception décide qu'il n'y a pas de
solution pour restaurer la situation et ne veut pas revenir en
arrière.
|
 |
 |
 |
The alternative is called
resumption. It means that the exception handler is expected to do
something to rectify the situation, and then the faulting method is retried,
presuming success the second time. If you want resumption, it means you still
hope to continue execution after the exception is handled. In this case, your
exception is more like a method call—which is how you should set up
situations in Java in which you want resumption-like behavior. (That is,
don’t throw an exception; call a method that fixes the problem.)
Alternatively, place your try block inside a while loop that keeps
reentering the try block until the result is
satisfactory.
|
 |
L'autre solution est appelée restauration. Cela signifie que le
gestionnaire d'exception est censé agir pour corriger la situation, et
ainsi la méthode incriminée est de nouveau exécutée avec un succès
présumé. Si vous voulez utilisez la restauration, cela signifie que
vous voulez que l'exécution continue après le traitement de
l'exception. Dans cette optique votre exception est résolue par un
appel de méthode qui est la façon dont vous devriez résoudre vos
problèmes en Java si vous voulez avoir un comportement de Type
restauration dans la gestion de vos exceptions. autrement placez votre
bloc try dans un bloc while qui continuera a exécuter le bloc
try tant que le résultat ne sera pas satisfaisant.
|
 |
 |
 |
Historically, programmers using operating
systems that supported resumptive exception handling eventually ended up using
termination-like code and skipping resumption. So although resumption sounds
attractive at first, it isn’t quite so useful in practice. The dominant
reason is probably the coupling that results:
your handler must often be aware of where the exception is thrown from and
contain nongeneric code specific to the throwing location. This makes the code
difficult to write and maintain, especially for large systems where the
exception can be generated from many
points.
|
 |
Historiquement, les programmeur utilisant des systèmes d'exploitation
qui supportaient la gestion des exceptions restauratrice finissaient
par utiliser un code qui ressemblait à celui de la terminaison
laissant de côté la restauration. Bien que la restauration ait l'air
attractive au départ elle n'est pas aisée à mettre en oeuvre. La
raison dominante est le couplage que cela générait : votre
gestionnaire d'exception doit être conscient de l'endroit ou est
générée l'exception et contenir du code générique indépendant de la
localisation de sa génération. Cela rend le code difficile à écrire et
à maintenir, surtout dans le cadre de grands systèmes où les
exceptions peuvent surgir de nulle part.
|
 |
 |
 |
Creating your own exceptions
|
 |
Créez vos propres Exceptions
|
 |
 |
 |
You’re not stuck using the existing
Java exceptions. This is important because you’ll
often need to create your own exceptions to denote a special error that your
library is capable of creating, but which was not foreseen when the Java
exception hierarchy was created.
|
 |
Vous n'êtes pas obligés de vous cantonner aux exceptions Java. Ceci
est important car vous aurez souvent besoin de créez vos exceptions
pour distinguer une erreur que votre librairie est capable de générer,
mais qui n'a pas été prévue lorsque la hiérarchie des exceptions Java
a été pensée.
|
 |
 |
 |
To create your own exception class,
you’re forced to inherit from an existing type of exception, preferably
one that is close in meaning to your new exception (this is often not possible,
however). The most trivial way to create a new type of exception is just to let
the compiler create the default constructor for you, so it requires almost no
code at all:
|
 |
Pour créer votre propre classe d'exception, vous devez hériter d'un
type d'exception déjà existant, de préférence une qui est proche de
votre nouvelle exception ( parfois ce n'est pas possible). La façon la
plus simple de créer une exception est de laisser le compilateur créer
le constructeur par défaut, ainsi vous n'avez pas besoin d'écrire de
code.
|
 |
 |
 |
//: c10:SimpleExceptionDemo.java // Inheriting your own exceptions. class SimpleException extends Exception {}
public class SimpleExceptionDemo { public void f() throws SimpleException { System.out.println( "Throwing SimpleException from f()"); throw new SimpleException (); } public static void main(String[] args) { SimpleExceptionDemo sed = new SimpleExceptionDemo(); try { sed.f(); } catch(SimpleException e) { System.err.println("Caught it!"); } } } ///:~
|
 |
"#009900">//: c10:SimpleExceptionDemo.java // Inheriting your own exceptions. class SimpleException "#0000FF">extends Exception {} public "#0000FF">class SimpleExceptionDemo { public "#0000FF">void f() "#0000FF">throws SimpleException { System.out.println( "Throwing SimpleException from f()"); throw "#0000FF">new SimpleException (); } public "#0000FF">static "#0000FF">void main(String[] args) { SimpleExceptionDemo sed = new SimpleExceptionDemo(); try { sed.f(); } catch(SimpleException e) { System.err.println("Caught it!"); } } } ///:~
|
 |
 |
 |
When the compiler creates the default
constructor, it which automatically (and invisibly) calls the base-class default
constructor. Of course, in this case you don’t get a
SimpleException(String) constructor, but in practice that isn’t
used much. As you’ll see, the most important thing about an exception is
the class name, so most of the time an exception like the one shown above is
satisfactory.
|
 |
Quand le compilateur crée le constructeur par défaut, celui ci
automatiquement appelle le constructeur de base par défaut de la
classe. Bien sûr vous n'obtenez pas un constructeur
SimpleException(String) par défaut mais ce constructeur n'est
guère utilisé. Comme vous le constaterez la chose la plus importante à
propos d'une exception est le nom de sa classe, donc la plupart du
temps une exception comme celle décrite au dessus est satisfaisante.
|
 |
 |
 |
Here, the result is printed to the
console standard error stream by writing to
System.err. This is usually a better place to
send error information than System.out, which may be redirected. If you
send output to System.err it will not be redirected along with
System.out so the user is more likely to notice it.
|
 |
Ici le résultat est envoyé vers le flux d'.erreur standard de
la console en écrivant dans System.err. C'est habituellement un
meilleur endroit pour diriger les informations sur les erreurs que
System.Out, qui peut être re-dirigé. Si vous envoyez le flux de
sortie vers System.err il ne sera pas re-dirigé de la même
façon que System.out donc l'utilisateur pourra le remarquer
plus aisément.
|
 |
 |
 |
Creating an exception class that also has
a constructor that takes a String is also quite simple:
|
 |
Créer une classe d'exception dont le constructeur a aussi un
constructeur qui prend un argument de type string est assez
simple :
|
 |
 |
 |
//: c10:FullConstructors.java // Inheriting your own exceptions.
class MyException extends Exception { public MyException() {} public MyException(String msg) { super(msg); } }
public class FullConstructors { public static void f() throws MyException { System.out.println( "Throwing MyException from f()"); throw new MyException(); } public static void g() throws MyException { System.out.println( "Throwing MyException from g()"); throw new MyException("Originated in g()"); } public static void main(String[] args) { try { f(); } catch(MyException e) { e.printStackTrace(System.err); } try { g(); } catch(MyException e) { e.printStackTrace(System.err); } } } ///:~
|
 |
//: c10:FullConstructors.java // Inheriting your own exceptions. class MyException "#0000FF">extends Exception { public MyException() {} public MyException(String msg) { super(msg); } } public "#0000FF">class FullConstructors { public "#0000FF">static void f() "#0000FF">throws MyException { System.out.println( "Throwing MyException from f()"); throw "#0000FF">new MyException(); } public "#0000FF">static void g() "#0000FF">throws MyException { System.out.println( "Throwing MyException from g()"); throw "#0000FF">new MyException("#004488">"Originated in g()"); } public "#0000FF">static "#0000FF">void main(String[] args) { try { f(); } catch(MyException e) { e.printStackTrace(System.err); } try { g(); } catch(MyException e) { e.printStackTrace(System.err); } } } ///:~
|
 |
 |
 |
The added code is small—the
addition of two constructors that define the way MyException is created.
In the second constructor, the base-class constructor with a String
argument is explicitly invoked by using the super
keyword.
|
 |
Le code ajouté est minime, deux constructeurs qui définissent la façon
dont MyException est crée. Dans le second constructeur, le
constructeur de base avec un argument de type String est appelé
de façon explicité avec le mot clé super.
|
 |
 |
 |
The stack trace information is sent to
System.err so that it’s more likely it will be noticed in the event
that System.out has been redirected.
|
 |
L'information de la pile des appels est redirigée vers System.err
ainsi on notera plus simplement dans l'événement que system.out a été
redirigé.
|
 |
 |
 |
The output of the program
is:
|
 |
La sortie du programme est :
|
 |
 |
 |
Throwing MyException from f() MyException at FullConstructors.f(FullConstructors.java:16) at FullConstructors.main(FullConstructors.java:24) Throwing MyException from g() MyException: Originated in g() at FullConstructors.g(FullConstructors.java:20) at FullConstructors.main(FullConstructors.java:29)
|
 |
Throwing MyException from f() MyException at FullConstructors.f(FullConstructors.java:16) at FullConstructors.main(FullConstructors.java:24) Throwing MyException from g() MyException: Originated in g() at FullConstructors.g(FullConstructors.java:20) at FullConstructors.main(FullConstructors.java:29)
|
 |
 |
 |
You can see the absence of the detail
message in the MyException thrown from f( ).
|
 |
Vous Pouvez noter l'absence de message de détail dans le
MyException généré depuis f().
|
 |
 |
 |
The process of creating your own
exceptions can be taken further. You can add extra constructors and
members:
|
 |
La création d'exception personnalisées peut être plus poussée. Vous
pouvez ajouter des constructeurs et des membres supplémentaires.
|
 |
 |
 |
//: c10:ExtraFeatures.java // Further embellishment of exception classes.
class MyException2 extends Exception { public MyException2() {} public MyException2(String msg) { super(msg); } public MyException2(String msg, int x) { super(msg); i = x; } public int val() { return i; } private int i; }
public class ExtraFeatures { public static void f() throws MyException2 { System.out.println( "Throwing MyException2 from f()"); throw new MyException2(); } public static void g() throws MyException2 { System.out.println( "Throwing MyException2 from g()"); throw new MyException2("Originated in g()"); } public static void h() throws MyException2 { System.out.println( "Throwing MyException2 from h()"); throw new MyException2( "Originated in h()", 47); } public static void main(String[] args) { try { f(); } catch(MyException2 e) { e.printStackTrace(System.err); } try { g(); } catch(MyException2 e) { e.printStackTrace(System.err); } try { h(); } catch(MyException2 e) { e.printStackTrace(System.err); System.err.println("e.val() = " + e.val()); } } } ///:~
|
 |
//: c10:ExtraFeatures.java // Further embellishment of exception classes. class MyException2 "#0000FF">extends Exception { public MyException2() {} public MyException2(String msg) { super(msg); } public MyException2(String msg, "#0000FF">int x) { super(msg); i = x; } public "#0000FF">int val() { return i; } private int i; } public "#0000FF">class ExtraFeatures { public "#0000FF">static void f() "#0000FF">throws MyException2 { System.out.println( "Throwing MyException2 from f()"); throw "#0000FF">new MyException2(); } public "#0000FF">static void g() "#0000FF">throws MyException2 { System.out.println( "Throwing MyException2 from g()"); throw "#0000FF">new MyException2("#004488">"Originated in g()"); } public "#0000FF">static void h() "#0000FF">throws MyException2 { System.out.println( "Throwing MyException2 from h()"); throw "#0000FF">new MyException2( "Originated in h()", 47); } public "#0000FF">static "#0000FF">void main(String[] args) { try { f(); } catch(MyException2 e) { e.printStackTrace(System.err); } try { g(); } catch(MyException2 e) { e.printStackTrace(System.err); } try { h(); } catch(MyException2 e) { e.printStackTrace(System.err); System.err.println("#004488">"e.val() = " + e.val()); } } } ///:~
|
 |
 |
 |
A data member i has been added,
along with a method that reads that value and an additional constructor that
sets it. The output is:
|
 |
Un membre i a été ajouté, avec une méthode qui lit cette donnée
et un constructeur supplémentaire qui l'initialise. Voici la sortie :
|
 |
 |
 |
Throwing MyException2 from f() MyException2 at ExtraFeatures.f(ExtraFeatures.java:22) at ExtraFeatures.main(ExtraFeatures.java:34) Throwing MyException2 from g() MyException2: Originated in g() at ExtraFeatures.g(ExtraFeatures.java:26) at ExtraFeatures.main(ExtraFeatures.java:39) Throwing MyException2 from h() MyException2: Originated in h() at ExtraFeatures.h(ExtraFeatures.java:30) at ExtraFeatures.main(ExtraFeatures.java:44) e.val() = 47
|
 |
Throwing MyException2 from f() MyException2 at ExtraFeatures.f(ExtraFeatures.java:22) at ExtraFeatures.main(ExtraFeatures.java:34) Throwing MyException2 from g() MyException2: Originated in g() at ExtraFeatures.g(ExtraFeatures.java:26) at ExtraFeatures.main(ExtraFeatures.java:39) Throwing MyException2 from h() MyException2: Originated in h() at ExtraFeatures.h(ExtraFeatures.java:30) at ExtraFeatures.main(ExtraFeatures.java:44) e.val() = 47
|
 |
 |
 |
Since an exception is just another kind
of object, you can continue this process of embellishing the power of your
exception classes. Keep in mind, however, that all this dressing-up might be
lost on the client programmers using your packages, since they might simply look
for the exception to be thrown and nothing more. (That’s the way most of
the Java library exceptions are used.)
|
 |
Puisqu'une exception est juste une sorte d'objet vous pouvez continuer
à enrichir vos classes d'exceptions mais gardez à l'esprit que toutes
ces améliorations peuvent êtres ignorées par les clients programmeurs
utilisant vos paquettages puisqu'ils vont probablement regarder quelle
exception pourra être générée et rien de plus. (C'est de cette façon
que sont utilisées le plus souvent les librairies d'exceptions Java).
|
 |
 |
 |
The exception
specification
|
 |
Spécifier des Exceptions
|
 |
 |
 |
In Java, you’re required to inform
the client programmer, who calls your method, of the exceptions that might be
thrown from your method. This is civilized, because the caller can know exactly
what code to write to catch all potential exceptions. Of course, if source code
is available, the client programmer could hunt through and look for throw
statements, but often a library doesn’t come with sources. To prevent this
from being a problem, Java provides syntax (and forces you to use that
syntax) to allow you to politely tell the client programmer what exceptions this
method throws, so the client programmer can handle them. This is the
exception specification, and it’s part of the method declaration,
appearing after the argument list.
|
 |
En java vous êtes obligé de fournir au programmeur qui appelle vos
méthodes la liste des exceptions pouvant être générées. C'est correct,
en effet le programmeur peut ainsi exactement savoir quel code écrire
pour attraper toute exception potentielle. Bien sur si le code source
est disponible le programmeur pourra y jeter un Sil et rechercher le
mot clé throw, mais souvent une librairie est livrée sans les
sources. Pour éviter que Cela soit un problème java fournit une
syntaxe (et vous oblige à l'utiliser) qui vous permet
d'informer formellement le programmeur client quelle exceptions est
générée par cette méthode, pour que le programmeur puisse les gérer.
c'est la spécification des exceptions et cela fait partie
intégrante de la déclaration de la méthode, elle apparaît après la
liste des arguments.
|
 |
 |
 |
The exception specification uses an
additional keyword, throws, followed by a list of all the potential
exception types. So your method definition might look like
this:
|
 |
La spécification des exceptions utilise un nouveau mot clé
throws suivi par la liste des type d'exceptions possibles. Vos
définitions de méthodes pourront ressembler à ceci :
|
 |
 |
 |
void f() throws TooBig, TooSmall, DivZero { //...
|
 |
void f() "#0000FF">throws TooBig, TooSmall, DivZero { "#009900">//...
|
 |
 |
 |
If you say
|
 |
Si vous écrivez
|
 |
 |
 |
void f() { // ...
|
 |
void f() { "#009900">// ...
|
 |
 |
 |
it means that no exceptions are thrown from the method. (Except for the exceptions of type RuntimeException, which can reasonably be thrown anywhere—this will be described later.)
|
 |
Cela signifie qu'aucune exception en pourra être générée par la
méthode. (Excepté les exceptions de type
RuntimeException, qui peut être générée n'importe où nous
verrons cela plus tard.)
|
 |
 |
 |
You can’t lie about an exception specification—if your method causes exceptions and doesn’t handle them, the compiler will detect this and tell you that you must either handle the exception or indicate with an exception specification that it may be thrown from your method. By enforcing exception specifications from top to bottom, Java guarantees that exception correctness can be ensured at compile-time[52].
|
 |
Vous ne pouvez pas mentir à propos de la spécification des exceptions,
si votre méthode génère des exceptions sans les gérer le compilateur
le détectera et vous dira que vous devez soit gérer ces exceptions ou
indiquer en spécifiant que cette exception peut être générée dans
votre méthode. En Forçant la spécification des exceptions de haut en
bas ,Java garantit que la correction des exceptions est assurée au
moment de la compilation.
|
 |
 |
 |
There is one place you can lie: you can claim to throw an exception that you really don’t. The compiler takes your word for it, and forces the users of your method to treat it as if it really does throw that exception. This has the beneficial effect of being a placeholder for that exception, so you can actually start throwing the exception later without requiring changes to existing code. It’s also important for creating abstract base classes and interfaces whose derived classes or implementations may need to throw exceptions.
|
 |
Il y a un endroit ou vous pouvez tricher : vous déclarez générer une
exception que vous ne n'allez pas générer. Le compilateur vous prend
au pied de la lettre, et force l'utilisateur de la méthode à agir
comme si elle pouvait générer l'exception. Ceci à l'effet positif
d'être un réceptacle pour cette exception, ainsi vous pourrez générer
l'exception sans devoir modifier le code existant. C'. est aussi
important pour créer des classes abstraites et des
interfaces dont les classes dérivées ou les implémentations
puissent générer des exceptions.
|
 |
 |
 |
Catching any exception
|
 |
Attraper n'importe quelle exception
|
 |
 |
 |
It is possible to create a handler that catches any type of exception. You do this by catching the base-class exception type Exception (there are other types of base exceptions, but Exception is the base that’s pertinent to virtually all programming activities):
|
 |
Il est possible de créer un gestionnaire qui intercepte n'importe quel
type d'exception. Ceci est réalisé en interceptant le classe de base
d'exception Exception (Il y a d'autre types d'exception de base
mais Exception est celle qui est pertinent pour tout les types
d'activités de programmation).
|
 |
 |
 |
catch(Exception e) { System.err.println("Caught an exception"); }
|
 |
catch(Exception e) { System.err.println("Caught an exception"); }
|
 |
 |
 |
This will catch any exception, so if you
use it you’ll want to put it at the end of your list of handlers to
avoid preempting any exception handlers that might otherwise follow
it.
|
 |
Ce code interceptera toute les exceptions donc si vous l'utilisez vous
voudrez le placer à la fin de votre liste de gestionnaires pour
éviter la préemption sur certains gestionnaires qui pourraient dans
l'autre cas le suivre.
|
 |
 |
 |
Since the Exception class is the
base of all the exception classes that are important to the programmer, you
don’t get much specific information about the exception, but you can call
the methods that come from its base type
Throwable:
|
 |
Comme la classe Exception est la base de toute les classes
d'exception qui sont utiles au programmeur, vous n'avez pas beaucoup
d'informations spécifiques sur l'exception, mais vous pouvez utiliser
les méthode venant de son type de base Throwable :
|
 |
 |
 |
String
getMessage( ) String
getLocalizedMessage( )Gets
the detail message, or a message adjusted for this particular
locale.
|
 |
String getMessage()
String getLocalizedMessage()
Donne le message détaillé ou un message adapté à cette localisation
particulière.
|
 |
 |
 |
String
toString( )Returns a short description
of the Throwable, including the detail message if there is one.
|
 |
String toString()
Retourne une courte description de l'objet Throwable ,incluant le
message détaillé si il y en a un.
|
 |
 |
 |
void
printStackTrace( )
void
printStackTrace(PrintStream) void
printStackTrace(PrintWriter)
Prints the Throwable and the
Throwable’s call stack trace. The call stack shows the sequence of method
calls that brought you to the point at which the exception was thrown. The first
version prints to standard error, the second and third prints to a stream of
your choice (in Chapter 11, you’ll understand why there are two types of
streams).
|
 |
void printStackTrace()
void printStackTrace(PrintStream)
void printStackTrace(PrintWriter)
Imprime l'objet throwable ainsi que la trace de la pile des
appels de l'objet Throwable. La pile d'appels vous montre la séquence
d'appels de méthodes qui vous ont conduit à l'endroit où l'exception a
été levée. La première version imprime les informations vers la sortie
standard la seconde et la troisième vers un flux de votre choix (Dans
le chapitre 11, vous comprendrez pourquoi il y a deux types de flux).
|
 |
 |
 |
Throwable
fillInStackTrace( )Records
information within this Throwable object about the current state of the
stack frames. Useful when an application is rethrowing an error or exception
(more about this shortly).
|
 |
Throwable fillInStackTrace()
Enregistre des informations liées à cet objet Throwable
concernant l'état de la « stack frame ». Utile quand une application
relance une exception (nous approfondirons cela plus loin).
|
 |
 |
 |
In addition, you get some other methods
from Throwable’s base type Object (everybody’s base
type). The one that might come in handy for exceptions is
getClass( ), which
returns an object representing the class of this object. You can in turn query
this Class object for its name with getName( ) or
toString( ). You can also do more sophisticated things with
Class objects that aren’t necessary in exception handling.
Class objects will be studied later in this book.
|
 |
En plus, vous pouvez utiliser des méthodes provenant de la classe mère
de Throwable qui est objet (ancêtre de tout type de base).
Celle qui pourrait être utile pour les exceptions est
getClass() qui retourne un objet représentant la classe de cet
objet. Vous pouvez interroger cet objet de Class avec les
méthodes getName() or toString(). Vous pouvez aussi
faire des choses plus sophistiquées avec l'objet Class qui ne
sont nécessaires dans la gestion des exceptions. Les objets
Class seront étudiés plus loin dans ce livre.
|
 |
 |
 |
Here’s an example that shows the
use of the basic Exception methods:
|
 |
Voici un exemple qui montre un emploi simple de la méthode
d'Exception de base :
|
 |
 |
 |
//: c10:ExceptionMethods.java // Demonstrating the Exception Methods.
public class ExceptionMethods { public static void main(String[] args) { try { throw new Exception("Here's my Exception"); } catch(Exception e) { System.err.println("Caught Exception"); System.err.println( "e.getMessage(): " + e.getMessage()); System.err.println( "e.getLocalizedMessage(): " + e.getLocalizedMessage()); System.err.println("e.toString(): " + e); System.err.println("e.printStackTrace():"); e.printStackTrace(System.err); } } } ///:~
|
 |
//: c10:ExceptionMethods.java // Demonstrating the Exception Methods. public "#0000FF">class ExceptionMethods { public "#0000FF">static "#0000FF">void main(String[] args) { try { throw "#0000FF">new Exception("#004488">"Here's my Exception"); } catch(Exception e) { System.err.println("Caught Exception"); System.err.println( "e.getMessage(): " + e.getMessage()); System.err.println( "e.getLocalizedMessage(): " + e.getLocalizedMessage()); System.err.println("e.toString(): " + e); System.err.println("#004488">"e.printStackTrace():"); e.printStackTrace(System.err); } } } ///:~
|
 |
 |
 |
The output for this program
is:
|
 |
La sortie du programme est :
|
 |
 |
 |
Caught Exception e.getMessage(): Here's my Exception e.getLocalizedMessage(): Here's my Exception e.toString(): java.lang.Exception: Here's my Exception e.printStackTrace(): java.lang.Exception: Here's my Exception at ExceptionMethods.main(ExceptionMethods.java:7) java.lang.Exception: Here's my Exception at ExceptionMethods.main(ExceptionMethods.java:7)
|
 |
Caught Exception e.getMessage(): Here's my Exception e.getLocalizedMessage(): Here's my Exception e.toString(): java.lang.Exception: Here's my Exception e.printStackTrace(): java.lang.Exception: Here's my Exception at ExceptionMethods.main(ExceptionMethods.java:7) java.lang.Exception: Here's my Exception at ExceptionMethods.main(ExceptionMethods.java:7)
|
 |
 |
 |
You can see that the methods provide
successively more information—each is effectively a superset of the
previous
one.
|
 |
Vous pouvez observer que les méthodes donnent successivement plus
d'informations, chacune est effectivement une évolution de la
précédente.
|
 |
 |
 |
Rethrowing an exception
|
 |
Relancer une exception
|
 |
 |
 |
Sometimes you’ll want to rethrow
the exception that you just caught, particularly when you use Exception
to catch any exception. Since you already have the reference to the current
exception, you can simply rethrow that reference:
|
 |
Quelques fois vous voudrez relancer une exception que vous venez
d'intercepter, particulièrement quand vous utilisez la classe
Exception pour attraper n'importe quelle exception. Comme vous
avez déjà la référence de l'exception courante vous pouvez tout
simplement la re-lancer.
>
|
 |
 |
 |
catch(Exception e) { System.err.println("An exception was thrown"); throw e; }
|
 |
catch(Exception e) { System.err.println("#004488">"An exception was thrown"); throw e; }
|
 |
 |
 |
Rethrowing an exception causes the
exception to go to the exception handlers in the next-higher context. Any
further catch clauses for the same try block are still ignored. In
addition, everything about the exception object is preserved, so the handler at
the higher context that catches the specific exception type can extract all the
information from that object.
|
 |
La redirection de l'exception envoie l'exception au gestionnaire
d'exception de contexte supérieur le plus proche. Tout autre clause
catch placée après dans le même bloc try est ignorée. De
plus, toute information concernant l'objet exception est préservée,
donc le gestionnaire d'exception du niveau supérieur qui peut attraper
ce type d'exception spécifique peut extraire toute les informations de
cet objet.
|
 |
 |
 |
If you simply rethrow the current
exception, the information that you print about that exception in
printStackTrace( )
will pertain to the exception’s origin, not the place where you
rethrow it. If you want to install new stack trace information, you can do so by
calling
fillInStackTrace( ),
which returns an exception object that it creates by stuffing the current stack
information into the old exception object. Here’s what it looks
like:
|
 |
Si vous redirigez simplement l'exception courante, l'information que
vous restituerez fera référence aux origines de l'exception et non de
l'endroit ou vous la redirigez. Si vous voulez placez de nouvelles
informations dans la pile des appels, vous pouvez le faire en appelant
la méthode fillInStackTrace(), qui retourne un objet exception
qu'elle a crée en ajoutant les informations actuelles de la pile dans
l'ancien objet exception. Voyons à quoi cela ressemble.
|
 |
 |
 |
//: c10:Rethrowing.java // Demonstrating fillInStackTrace()
public class Rethrowing { public static void f() throws Exception { System.out.println( "originating the exception in f()"); throw new Exception("thrown from f()"); } public static void g() throws Throwable { try { f(); } catch(Exception e) { System.err.println( "Inside g(), e.printStackTrace()"); e.printStackTrace(System.err); throw e; // 17 // throw e.fillInStackTrace(); // 18 } } public static void main(String[] args) throws Throwable { try { g(); } catch(Exception e) { System.err.println( "Caught in main, e.printStackTrace()"); e.printStackTrace(System.err); } } } ///:~
|
 |
//: c10:Rethrowing.java // Demonstrating fillInStackTrace() public "#0000FF">class Rethrowing { public "#0000FF">static void f() "#0000FF">throws Exception { System.out.println( "originating the exception in f()"); throw "#0000FF">new Exception("#004488">"thrown from f()"); } public "#0000FF">static void g() "#0000FF">throws Throwable { try { f(); } catch(Exception e) { System.err.println( "Inside g(), e.printStackTrace()"); e.printStackTrace(System.err); throw e; "#009900">// 17 // throw e.fillInStackTrace(); // 18 } } public "#0000FF">static void main(String[] args) throws Throwable { try { g(); } catch(Exception e) { System.err.println( "Caught in main, e.printStackTrace()"); e.printStackTrace(System.err); } } } ///:~
|
 |
 |
 |
The important line numbers are marked as
comments. With line 17 uncommented (as shown), the output is:
|
 |
Les numéros des lignes importantes sont marquées dans les
commentaires, avec la ligne 17 non mise en commentaire (cf. le code
ci-dessus) l'exécution produit comme sortie :
|
 |
 |
 |
originating the exception in f() Inside g(), e.printStackTrace() java.lang.Exception: thrown from f() at Rethrowing.f(Rethrowing.java:8) at Rethrowing.g(Rethrowing.java:12) at Rethrowing.main(Rethrowing.java:24) Caught in main, e.printStackTrace() java.lang.Exception: thrown from f() at Rethrowing.f(Rethrowing.java:8) at Rethrowing.g(Rethrowing.java:12) at Rethrowing.main(Rethrowing.java:24)
|
 |
originating the exception in f() Inside g(), e.printStackTrace() java.lang.Exception: thrown from f() at Rethrowing.f(Rethrowing.java:8) at Rethrowing.g(Rethrowing.java:12) at Rethrowing.main(Rethrowing.java:24) Caught in main, e.printStackTrace() java.lang.Exception: thrown from f() at Rethrowing.f(Rethrowing.java:8) at Rethrowing.g(Rethrowing.java:12) at Rethrowing.main(Rethrowing.java:24)
|
 |
 |
 |
So the exception stack trace always
remembers its true point of origin, no matter how many times it gets
rethrown.
|
 |
Ainsi la trace de la pile d'exception se souvient toujours de sont
vrai point d'origine, sans tenir compte du nombre de fois qu'il sera
relancé.
|
 |
 |
 |
With line 17 commented and line 18
uncommented, fillInStackTrace( ) is used instead, and the result
is:
|
 |
Avec la ligne 17 mise en commentaire et la ligne 18 décommentée
fillInStackTrace() est utilisée ce qui donne le résultat
suivant :
|
 |
 |
 |
originating the exception in f() Inside g(), e.printStackTrace() java.lang.Exception: thrown from f() at Rethrowing.f(Rethrowing.java:8) at Rethrowing.g(Rethrowing.java:12) at Rethrowing.main(Rethrowing.java:24) Caught in main, e.printStackTrace() java.lang.Exception: thrown from f() at Rethrowing.g(Rethrowing.java:18) at Rethrowing.main(Rethrowing.java:24)
|
 |
originating the exception in f() Inside g(), e.printStackTrace() java.lang.Exception: thrown from f() at Rethrowing.f(Rethrowing.java:8) at Rethrowing.g(Rethrowing.java:12) at Rethrowing.main(Rethrowing.java:24) Caught in main, e.printStackTrace() java.lang.Exception: thrown from f() at Rethrowing.g(Rethrowing.java:18) at Rethrowing.main(Rethrowing.java:24)
|
 |
 |
 |
Because of
fillInStackTrace( ), line 18 becomes the new
point of origin of the exception.
|
 |
Grâce à fillInStackTrace() la ligne 18 devient l'origine de
l'exception.
|
 |
 |
 |
The class Throwable must appear in
the exception specification for g( ) and main( ) because
fillInStackTrace( ) produces a reference to a Throwable
object. Since Throwable is a base class of
Exception, it’s possible to get an object that’s a
Throwable but not an Exception, so the handler for
Exception in main( ) might miss it. To make sure everything
is in order, the compiler forces an exception specification for
Throwable. For example, the exception in the following program is
not caught in main( ):
|
 |
La classe Throwable doit apparaître dans la spécification
d'exception pour g() et main() parce que
fillInStackTrace() produit une référence à un objet
Throwable. Comme Throwable est la classe de base de
toute Exception il est possible d'avoir un objet de type
Throwable qui ne soit pas une Exception et donc
que le gestionnaire d'exception du main() ne le traite pas.
Pour être sur que tout soit correct le compilateur force une
spécification d'exception pour Throwable. Par exemple
l'exception dans le programme suivant n'est pas interceptée
dans main() :
|
 |
 |
 |
//: c10:ThrowOut.java public class ThrowOut { public static void main(String[] args) throws Throwable { try { throw new Throwable(); } catch(Exception e) { System.err.println("Caught in main()"); } } } ///:~
|
 |
//: c10:ThrowOut.java public "#0000FF">class ThrowOut { public "#0000FF">static void main(String[] args) throws Throwable { try { throw "#0000FF">new Throwable(); } catch(Exception e) { System.err.println("Caught in main()"); } } } ///:~
|
 |
 |
 |
It’s also possible to rethrow a
different exception from the one you caught. If you do this, you get a similar
effect as when you use fillInStackTrace( )—the information
about the original site of the exception is lost, and what you’re left
with is the information pertaining to the new throw:
|
 |
Il est aussi possible de rediriger une exception différente de celle
que vous avez intercepté. En procédant ainsi vous obtenez une effet
similaire a l'utilisation de fillInStackTrace() . l'information
sur l'emplacement originel de l'exception est perdu, et l'information
qu'il vous reste est celle relative au nouveau throw() :
|
 |
 |
 |
//: c10:RethrowNew.java // Rethrow a different object // from the one that was caught.
class OneException extends Exception { public OneException(String s) { super(s); } }
class TwoException extends Exception { public TwoException(String s) { super(s); } }
public class RethrowNew { public static void f() throws OneException { System.out.println( "originating the exception in f()"); throw new OneException("thrown from f()"); } public static void main(String[] args) throws TwoException { try { f(); } catch(OneException e) { System.err.println( "Caught in main, e.printStackTrace()"); e.printStackTrace(System.err); throw new TwoException("from main()"); } } } ///:~
|
 |
//: c10:RethrowNew.java // Rethrow a different object // from the one that was caught. class OneException "#0000FF">extends Exception { public OneException(String s) { "#0000FF">super(s); } } class TwoException "#0000FF">extends Exception { public TwoException(String s) { "#0000FF">super(s); } } public "#0000FF">class RethrowNew { public "#0000FF">static void f() "#0000FF">throws OneException { System.out.println( "originating the exception in f()"); throw "#0000FF">new OneException("#004488">"thrown from f()"); } public "#0000FF">static "#0000FF">void main(String[] args) throws TwoException { try { f(); } catch(OneException e) { System.err.println( "Caught in main, e.printStackTrace()"); e.printStackTrace(System.err); throw "#0000FF">new TwoException("#004488">"from main()"); } } } ///:~
|
 |
 |
 |
The output is:
|
 |
Le résultat de l'exécution est :
|
 |
 |
 |
originating the exception in f() Caught in main, e.printStackTrace() OneException: thrown from f() at RethrowNew.f(RethrowNew.java:17) at RethrowNew.main(RethrowNew.java:22) Exception in thread "main" TwoException: from main() at RethrowNew.main(RethrowNew.java:27)
|
 |
originating the exception in f() Caught in main, e.printStackTrace() OneException: thrown from f() at RethrowNew.f(RethrowNew.java:17) at RethrowNew.main(RethrowNew.java:22) Exception in thread "#004488">"main" TwoException: from main() at RethrowNew.main(RethrowNew.java:27)
|
 |
 |
 |
The final exception knows only that it
came from main( ), and not from f( ).
|
 |
L'exception finale sait seulement qu'elle vient de main() et
non de f().
|
 |
 |
 |
You never have to worry about cleaning up
the previous exception, or any exceptions for that matter. They’re all
heap-based objects created with new, so the garbage collector
automatically cleans them all
up.
|
 |
Vous n'avez pas à vous soucier de la destruction des exceptions
précédentes. Ce sont tout des objets crées avec l'instruction
new(), le garbage collector les détruits donc automatiquement.
|
 |
 |
 |
Standard Java exceptions
|
 |
Les exceptions Java standard
|
 |
 |
 |
The Java class Throwable describes
anything that can be thrown as an exception. There are two general types of
Throwable objects (“types of” = “inherited
from”). Error represents compile-time and
system errors that you don’t worry about catching (except in special
cases). Exception is the basic type that can be
thrown from any of the standard Java library class methods and from your methods
and run-time accidents. So the Java programmer’s base type of interest is
Exception.
|
 |
La classe Java Throwable décrit tout ce qui peut être généré
comme exception. Il y a deux sortes d'objets Throwable («
Sortes de » = « Héritées de »). Error représente les erreurs systèmes
et de compilation dont vous n'avez pas à vous soucier (excepté
quelques cas spécifiques). Exception est le type de base qui
peut être généré à partir de n'importe quelle méthode de classe de
librairie Java standard. Les Exceptions sont donc le type de
base qui intéresse le programmeur Java.
|
 |
 |
 |
The best way to get an overview of the
exceptions is to browse the HTML Java documentation that you can download from
java.sun.com. It’s worth doing this once just to get a feel for the
various exceptions, but you’ll soon see that there isn’t anything
special between one exception and the next except for the name. Also, the number
of exceptions in Java keeps expanding; basically it’s pointless to print
them in a book. Any new library you get from a third-party vendor will probably
have its own exceptions as well. The important thing to understand is the
concept and what you should do with the exceptions.
|
 |
La meilleure façon d'avoir un aperçu des exceptions est de lire la
documentation HTML de Java qui est disponible à java.sun.com.
Il est utile de le faire juste pour s'apercevoir de la variété des
exception, mais vous verrez rapidement que rien à part le nom ne
distingue une exception d'une autre. Comme le nombre d'exceptions Java
continue de s'accroître il est inutile d'en imprimer la liste. Chaque
nouvelle librairie que vous achèterez à un éditeur aura probablement
ses propres exceptions. Le point important à comprendre est le concept
et ce que vous devez faire avec les exceptions.
|
 |
 |
 |
The basic idea is that the name of the
exception represents the problem that occurred, and the exception name is
intended to be relatively self-explanatory. The exceptions are not all defined
in java.lang; some are created to support other libraries such as
util, net, and io, which you can see from their full class
names or what they are inherited from. For example, all I/O exceptions are
inherited from
java.io.IOException.
|
 |
Le principe de base est que le nom de l'exception représente le
problème qui est apparu, et le nom de l'exception est censé être
relativement explicite. Toutes les exceptions ne sont pas toutes
définies dans java.lang ; certaines ont été crées pour être
utilisées dans d'autres libraires telles que util, net
et io ce que l'on peut voir à partir du nom complet des classes
dont elles ont héritées. Ainsi toutes les exception I/O
(Entrée/Sortie) héritent de java.io.IOException.
|
 |
 |
 |
The special case of RuntimeException
|
 |
Le cas particulier RuntimeException
|
 |
 |
 |
The first example in this chapter
was
|
 |
Le premier exemple du chapitre était :
|
 |
 |
 |
if(t == null) throw new NullPointerException();
|
 |
if(t == "#0000FF">null) throw "#0000FF">new NullPointerException();
|
 |
 |
 |
 |
 |
 |
 |
 |
|
 |
 |
 |