751 votes

Comprendre les exceptions vérifiées et non vérifiées en Java

Joshua Bloch dans " Java efficace " a dit que

Utilisez les exceptions vérifiées pour les conditions récupérables et le temps d'exécution exceptions d'exécution pour les erreurs de programmation (Point 58 dans la 2e édition)

Voyons si je comprends bien.

Voici ce que je comprends d'une exception contrôlée :

try{
    String userInput = //read in user input
    Long id = Long.parseLong(userInput);
}catch(NumberFormatException e){
    id = 0; //recover the situation by setting the id to 0
}

1. Ce qui précède est-il considéré comme une exception vérifiée ?

2. RuntimeException est-elle une exception non vérifiée ?

Voici ce que je comprends d'une exception non vérifiée :

try{
    File file = new File("my/file/path");
    FileInputStream fis = new FileInputStream(file);   
}catch(FileNotFoundException e){

//3. What should I do here?
    //Should I "throw new FileNotFoundException("File not found");"?
    //Should I log?
    //Or should I System.exit(0);?
}

4. Maintenant, le code ci-dessus ne pourrait-il pas également être une exception vérifiée ? Je peux essayer de rétablir la situation comme ceci ? Est-ce que je peux ? (Remarque : ma troisième question se trouve à l'intérieur du catch ci-dessus)

try{
    String filePath = //read in from user input file path
    File file = new File(filePath);
    FileInputStream fis = new FileInputStream(file);   
}catch(FileNotFoundException e){
    //Kindly prompt the user an error message
    //Somehow ask the user to re-enter the file path.
}

5. Pourquoi les gens font-ils cela ?

public void someMethod throws Exception{

}

Pourquoi laissent-ils l'exception remonter à la surface ? Ne vaut-il pas mieux traiter l'erreur plus tôt ? Pourquoi faire des bulles ?

6. Dois-je mettre en évidence l'exception exacte ou la masquer en utilisant Exception ?

Voici mes lectures

En Java, quand dois-je créer une exception vérifiée et quand dois-je créer une exception d'exécution ?

Quand choisir les exceptions cochées et non cochées ?

8 votes

J'ai un excellent exemple d'exception non vérifiée. J'ai un DataSeries qui contient des données qui doivent toujours rester dans l'ordre chronologique. Il existe une méthode pour ajouter une nouvelle DataPoint à l'extrémité d'un DataSeries . Si l'ensemble de mon code fonctionne correctement tout au long du projet, une DataPoint ne doit jamais être ajouté à la fin qui a une date antérieure à celle déjà sur la fin. Chaque module de l'ensemble du projet est construit avec ce truisme. Cependant, je vérifie cette condition et je lève une exception non vérifiée si cela se produit. Pourquoi ? Si cela se produit, je veux savoir qui fait cela et le réparer.

3 votes

Pour ajouter encore plus de confusion. De nombreuses personnes préconisaient les exceptions vérifiées il y a 10 ans, mais aujourd'hui, l'opinion se rapproche de plus en plus de l'idée que les exceptions vérifiées sont mauvaises. (Je ne suis cependant pas d'accord sur ce point)

0 votes

513voto

Bozho Points 273663

Beaucoup de gens disent que les exceptions vérifiées (c'est-à-dire celles que vous devez explicitement attraper ou relancer) ne devraient pas être utilisées du tout. Elles ont été éliminées en C# par exemple, et la plupart des langages n'en ont pas. Vous pouvez donc toujours lancer une sous-classe de RuntimeException (exception non vérifiée)

Cependant, je pense que les exceptions vérifiées sont utiles - elles sont utilisées lorsque vous voulez forcer l'utilisateur de votre API à réfléchir à la manière de gérer la situation exceptionnelle (si elle est récupérable). C'est juste que les exceptions vérifiées sont surutilisées dans la plate-forme Java, ce qui fait que les gens les détestent.

Voici mon point de vue élargi sur le sujet .

Quant aux questions particulières :

  1. Est-ce que le NumberFormatException envisager une exception vérifiée ?
    Non. NumberFormatException n'est pas vérifié (= est une sous-classe de RuntimeException ). Pourquoi ? Je n'en sais rien. (mais il aurait dû y avoir une méthode isValidInteger(..) )

  2. Es RuntimeException une exception non vérifiée ?
    Oui, exactement.

  3. Que dois-je faire ici ?
    Cela dépend de l'endroit où se trouve ce code et de ce que vous voulez qu'il se passe. S'il se trouve dans la couche interface utilisateur, il faut l'attraper et afficher un avertissement. S'il se trouve dans la couche service, il ne faut pas l'attraper du tout et le laisser bouillonner. Mais n'avalez pas l'exception. Si une exception se produit dans la plupart des cas, vous devez choisir l'une des options suivantes :

    • l'enregistrer et le renvoyer
    • le relancer (déclarer qu'il sera relancé par la méthode)
    • construire une nouvelle exception en passant l'exception courante dans le constructeur
  4. Maintenant, le code ci-dessus ne pourrait-il pas également être une exception vérifiée ? Je peux essayer de rétablir la situation comme ceci ? Je peux ?
    Ça aurait pu l'être. Mais rien ne vous empêche d'attraper aussi l'exception non vérifiée.

  5. Pourquoi les gens ajoutent-ils des classes Exception dans la clause "throws" ?
    Le plus souvent parce que les gens sont paresseux et ne savent pas quoi attraper et quoi relancer. Lancer Exception est une mauvaise pratique et doit être évitée.

Hélas, il n'existe pas de règle unique permettant de déterminer quand il faut attraper, quand il faut relancer, quand il faut utiliser des exceptions vérifiées et quand il faut utiliser des exceptions non vérifiées. Je suis d'accord pour dire que cela provoque beaucoup de confusion et beaucoup de mauvais code. Le principe général est énoncé par Bloch (vous en avez cité une partie). Et le principe général est de relancer une exception vers la couche où vous pouvez la traiter.

38 votes

En ce qui concerne la levée d'exception, ce n'est pas toujours parce que les gens sont paresseux, il est également courant que, lorsque vous mettez en œuvre des cadres, vous laissiez les utilisateurs du cadre être en mesure de lever n'importe quelle exception. Vous pouvez, par exemple, vérifier la signature de l'interface Callable dans JSE.

0 votes

@Bozho : Vous avez répondu 1, 2, 4 et 5 et les avez appelés 1, 2, 3 et 4. La bonne question 3 est cachée dans le bloc de code.

10 votes

@Kaj - oui, des choses aussi générales que Callable, interceptors et autres sont des cas particuliers. Mais dans la plupart des cas, c'est parce que les gens sont paresseux :)

254voto

Michael Borgwardt Points 181658

Le fait que quelque chose soit une "exception vérifiée" n'a rien à voir avec le fait que vous l'attrapiez ou avec ce que vous faites dans le bloc catch. C'est une propriété des classes d'exceptions. Tout ce qui est une sous-classe de Exception sauf pour RuntimeException et ses sous-classes est une exception vérifiée.

Le compilateur Java vous oblige soit à attraper les exceptions vérifiées, soit à les déclarer dans la signature de la méthode. Cela était censé améliorer la sécurité du programme

Pourquoi laissent-ils la bulle d'exception l'exception ? N'est-il pas préférable de gérer l'erreur le plus tôt possible mieux ? Pourquoi faire des bulles ?

Parce que c'est l'entière point d'exceptions. Sans cette possibilité, vous n'auriez pas besoin d'exceptions. Elles vous permettent de gérer les erreurs à un niveau que vous choisissez, plutôt que de vous obliger à les traiter dans les méthodes de bas niveau où elles se produisent initialement.

3 votes

Merci. Il m'arrive de lancer des exceptions hors de mes méthodes en raison du principe "crap in crape out". Si l'un des développeurs de mon équipe veut entrer une expression xpath invalide, c'est à lui de gérer l'exception. Dans le cas peu probable où il attrape une exception et ne fait rien, il en entendra parler lors de la revue de code.

13 votes

"Tout ce qui est une sous-classe de Throwable, à l'exception de RuntimeException et de ses sous-classes, est une exception vérifiée." - Votre affirmation est incorrecte. Error hérite également de Throwable et elle n'est pas vérifiée.

0 votes

Pouvez-vous développer un peu plus les problèmes de conception qu'il crée ? J'ai le sentiment qu'il serait problématique d'avoir tous les throws dans les signatures de vos méthodes, mais j'ai du mal à argumenter contre les exceptions vérifiées dans un contexte plus large.

78voto

d-live Points 3464
  1. Ce qui précède est-il considéré comme une exception vérifiée ? Non Le fait que vous traitiez une exception n'en fait pas pour autant une Checked Exception s'il s'agit d'un RuntimeException .

  2. Es RuntimeException un unchecked exception ? Oui

Checked Exceptions son subclasses de java.lang.Exception Unchecked Exceptions son subclasses de java.lang.RuntimeException

Les appels lançant des exceptions vérifiées doivent être inclus dans un bloc try{} ou traités à un niveau supérieur dans l'appelant de la méthode. Dans ce cas, la méthode courante doit déclarer qu'elle lève lesdites exceptions afin que les appelants puissent prendre les dispositions appropriées pour gérer l'exception.

J'espère que cela vous aidera.

Q : Dois-je mettre en bulle l'exception exacte exacte ou la masquer en utilisant l'exception ?

R : Oui, c'est une très bonne question et une considération importante pour la conception. La classe Exception est une classe d'exception très générale et peut être utilisée pour envelopper des exceptions internes de bas niveau. Il est préférable de créer une exception personnalisée et de l'intégrer. Mais, et c'est un point important, n'occultez jamais la cause première sous-jacente. Par exemple Don't ever faire ce qui suit -

try {
     attemptLogin(userCredentials);
} catch (SQLException sqle) {
     throw new LoginFailureException("Cannot login!!"); //<-- Eat away original root cause, thus obscuring underlying problem.
}

Faites plutôt ce qui suit :

try {
     attemptLogin(userCredentials);
} catch (SQLException sqle) {
     throw new LoginFailureException(sqle); //<-- Wrap original exception to pass on root cause upstairs!.
}

Le fait de ronger la cause première originale enterre la cause réelle au-delà de toute récupération est un cauchemar pour les équipes de support de production qui n'ont accès qu'aux journaux d'application et aux messages d'erreur. Bien que ces derniers soient mieux conçus, beaucoup de gens ne les utilisent pas souvent car les développeurs ne transmettent pas le message sous-jacent à l'appelant. Alors, prenez-en bonne note : Always pass on the actual exception de retour, qu'il soit ou non enveloppé dans une exception spécifique à l'application.

Sur le try-catching RuntimeExceptions

RuntimeException en règle générale, ne doivent pas faire l'objet d'un try-catched. Ils signalent généralement une erreur de programmation et doivent être laissés de côté. Au lieu de cela, le programmeur devrait vérifier la condition d'erreur avant d'invoquer un code qui pourrait résulter en une erreur d'exécution. RuntimeException . Par exemple :

try {
    setStatusMessage("Hello Mr. " + userObject.getName() + ", Welcome to my site!);
} catch (NullPointerException npe) {
   sendError("Sorry, your userObject was null. Please contact customer care.");
}

C'est une mauvaise pratique de programmation. Au lieu de cela, un contrôle de nullité aurait dû être effectué comme -

if (userObject != null) {
    setStatusMessage("Hello Mr. " + userObject.getName() + ", Welome to my site!);
} else {
   sendError("Sorry, your userObject was null. Please contact customer care.");
}

Mais il arrive que la vérification des erreurs soit coûteuse, par exemple pour le formatage des nombres.

try {
    String userAge = (String)request.getParameter("age");
    userObject.setAge(Integer.parseInt(strUserAge));
} catch (NumberFormatException npe) {
   sendError("Sorry, Age is supposed to be an Integer. Please try again.");
}

Dans ce cas, le contrôle d'erreur pré-invocationnel ne vaut pas la peine, car il signifie essentiellement la duplication de tout le code de conversion des chaînes de caractères en nombres entiers dans la méthode parseInt() - et il est sujet à des erreurs s'il est mis en œuvre par un développeur. Il est donc préférable de se passer de try-catch.

Alors NullPointerException y NumberFormatException sont tous deux RuntimeExceptions en attrapant un NullPointerException devrait être remplacée par une vérification gracieuse de la nullité, tandis que je recommande d'attraper un NumberFormatException explicitement pour éviter l'introduction éventuelle d'un code sujet à des erreurs.

0 votes

Merci. Une autre question quand vous faites des bulles dans le exception je dois faire apparaître l'exception exacte dans une bulle ou la masquer en utilisant Exception . J'écris du code au-dessus d'un code existant, et Exception en train de bouillonner un peu partout. Je me demande si c'est le comportement correct ?

1 votes

C'est une très bonne et importante question, j'ai modifié ma réponse pour inclure l'explication.

0 votes

Merci beaucoup. Serait-il possible pour vous de me montrer le contenu de LoginFailureException(sqle) ?

20voto

Aleadam Points 25433

1 . Si vous n'êtes pas sûr d'une exception, consultez l'API :

 java.lang.Object
 extended by java.lang.Throwable
  extended by java.lang.Exception
   extended by java.lang.RuntimeException  //<-NumberFormatException is a RuntimeException  
    extended by java.lang.IllegalArgumentException
     extended by java.lang.NumberFormatException

2 . Oui, et chaque exception qui la prolonge.

3 . Il n'est pas nécessaire d'attraper et de lancer la même exception. Vous pouvez afficher un nouveau dialogue de fichier dans ce cas.

4 . FileNotFoundException es déjà une exception vérifiée.

5 . S'il est prévu que la méthode d'appel someMethod pour attraper l'exception, cette dernière peut être lancée. Il ne fait que "passer la balle". Un exemple de son utilisation serait si vous voulez la lancer dans vos propres méthodes privées, et traiter l'exception dans votre méthode publique à la place.

Une bonne lecture est le document Oracle lui-même : http://download.oracle.com/javase/tutorial/essential/exceptions/runtime.html

Pourquoi les concepteurs ont-ils décidé d'obliger une méthode à spécifier toutes les exceptions vérifiées non attrapées qui peuvent être lancées dans sa portée ? Toute exception pouvant être levée par une méthode fait partie de l'interface de programmation publique de la méthode. Les personnes qui appellent une méthode doivent connaître les exceptions qu'elle peut lever afin de pouvoir décider de ce qu'elles doivent faire. Ces exceptions font autant partie de l'interface de programmation de cette méthode que ses paramètres et sa valeur de retour.

La prochaine question pourrait être : "Si c'est si bien de documenter l'API d'une méthode, inc.

Il y a également une information importante dans le document intitulé Spécification du langage Java :

Les classes d'exceptions vérifiées nommées dans la clause throws font partie du contrat entre l'implémenteur et l'utilisateur de la méthode ou du constructeur. .

L'essentiel, à mon avis, est que vous puede attraper n'importe quel RuntimeException Mais vous n'êtes pas obligé de le faire et, en fait, l'implémentation n'est pas obligée de maintenir les mêmes exceptions non vérifiées lancées, car elles ne font pas partie du contrat.

0 votes

Merci. Une autre question quand vous faites des bulles dans le exception Je dois faire apparaître l'exception exacte dans une bulle ou la masquer en utilisant la fonction Exception . J'écris du code au-dessus d'un code existant, et Exception en train de bouillonner un peu partout. Je me demande si c'est le comportement correct ?

1 votes

@Harry Je vais laisser les personnes ayant plus de connaissances que moi répondre à cette question : stackoverflow.com/questions/409563/

10voto

dontocsata Points 922

1) Non, une NumberFormatException est une exception non vérifiée. Même si vous l'avez attrapée (vous n'êtes pas obligé de le faire) parce qu'elle n'est pas vérifiée. C'est parce que c'est une sous-classe de IllegalArgumentException qui est une sous-classe de RuntimeException .

2) RuntimeException est la racine de toutes les exceptions non vérifiées. Chaque sous-classe de RuntimeException n'est pas vérifié. Toutes les autres exceptions et Throwable sont vérifiées, à l'exception des erreurs (qui relèvent de l'article 3). Throwable ).

3/4) Vous pourriez avertir l'utilisateur qu'il a choisi un fichier inexistant et lui demander d'en choisir un nouveau. Ou simplement arrêter d'informer l'utilisateur qu'il a saisi quelque chose d'invalide.

5) Lancer et attraper 'Exception' est une mauvaise pratique. Mais de manière plus générale, vous pouvez lancer d'autres exceptions pour que l'appelant puisse décider de la manière de les traiter. Par exemple, si vous avez écrit une bibliothèque pour gérer la lecture d'un fichier d'entrée et que l'on transmet à votre méthode un fichier inexistant, vous n'avez aucune idée de la façon de gérer cette situation. L'appelant veut-il redemander ou quitter ? Vous lancez donc l'exception en amont de la chaîne vers l'appelant.

Dans de nombreux cas, un unchecked Exception se produit parce que le programmeur n'a pas vérifié les entrées (dans le cas de NumberFormatException dans votre première question). C'est pourquoi il est facultatif de les attraper, car il existe des moyens plus élégants d'éviter de générer ces exceptions.

0 votes

Merci. Une autre question quand vous faites des bulles dans le exception Je dois faire apparaître l'exception exacte dans une bulle ou la masquer en utilisant la fonction Exception . J'écris du code au-dessus d'un code existant, et Exception en train de bouillonner un peu partout. Je me demande si c'est le comportement correct ?

0 votes

Vous pouvez soit faire en sorte que votre méthode lève également une exception (ce qui n'est pas idéal). Ou attraper l'exception et lancer une meilleure exception (comme IOException ou autre). Toutes les exceptions peuvent prendre une exception dans leur constructeur comme "cause", donc vous devriez l'utiliser.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X