23 votes

Exceptions vérifiées et non vérifiées en Java

J'ai quelques difficultés à comprendre les différences entre checked y unchecked les exceptions en Java.

  1. Tout d'abord, checked Les exceptions sont censées rechercher les anomalies au moment de la compilation. Les exemples fournis dans différentes sources citent la connectivité des bases de données, la gestion des fichiers, etc. unchecked Les exceptions sont censées rechercher les erreurs du programmeur, comme l'indexation au-delà de la plage d'un tableau, etc.

Cela ne devrait-il pas être l'inverse ? Je veux dire, la connectivité de la base de données est faite pendant l'exécution, non ? Il en va de même pour la gestion des fichiers. Vous n'ouvrez pas un fichier au moment de la compilation, alors pourquoi une erreur éventuelle à ce sujet serait-elle recherchée au moment de la compilation ? D'un autre côté, l'indexation d'un tableau au-delà de sa plage est déjà faite dans le programme, ce qui peut être vérifié pendant la compilation (si l'index anormal est fourni par l'utilisateur pendant l'exécution, alors il est normal que ce soit un problème d'exécution). Qu'est-ce qui me manque ici ?

2 Deuxièmement, comment RunTimeException lui-même étant unchecked , sous-classe Exception qui est checked ? Qu'est-ce que cela signifie ?

J'ai trouvé un exemple dans le livre d'Herbert Schildt expliquant l'utilisation de la fonction checked exceptions :

class ThrowsDemo {
   public static char prompt(String str)
      throws java.io.IOException {
  System.out.print(str + ": ");
  return (char) System.in.read();
  }
  public static void main(String args[]) {
    char ch;
    try {
      ch = prompt("Enter a letter");
    }
    catch(java.io.IOException exc) {
     System.out.println("I/O exception occurred.");
     ch = 'X';
    }
    System.out.println("You pressed " + ch);
    }
}

Est-ce que le throws clause nécessaire ici ? Pourquoi je ne peux pas le faire normalement avec un try-catch comme ceci (désolé, je ne sais pas comment simuler une IO Exception Je n'ai donc pas pu le vérifier moi-même !)

class ThrowsDemo {
   public static char prompt(String str)  {
     System.out.print(str + ": ");
     return (char) System.in.read();
  }
  public static void main(String args[]) {
    char ch;
    try {
      ch = prompt("Enter a letter");
    }
    catch(java.io.IOException exc) {
     System.out.println("I/O exception occurred.");
     ch = 'X';
    }
    System.out.println("You pressed " + ch);
    }
}

29voto

Luigi R. Viggiano Points 3104

Les exceptions vérifiées doivent être gérées par l'appelant, les exceptions non vérifiées ne le sont pas.

Ainsi, lorsque vous concevez votre application, vous devez tenir compte du type de situation exceptionnelle que vous gérez.

Par exemple, si vous concevez une méthode de validation qui vérifie la validité d'une entrée utilisateur, vous savez que l'appelant doit vérifier l'exception de validation et afficher les erreurs à l'utilisateur d'une manière agréable. Il doit s'agir d'une exception vérifiée.

Ou, pour les conditions exceptionnelles qui peuvent être récupérées : imaginez que vous avez un équilibreur de charge et que vous voulez notifier à l'appelant qu'un des "n" serveurs est en panne, l'appelant doit donc récupérer l'incident en réacheminant le message vers un autre serveur ; cela devrait être une exception vérifiée, parce qu'il est crucial que l'appelant (client) essaie de récupérer l'erreur, et ne laisse pas l'erreur interrompre le déroulement du programme.

Au contraire, il existe de nombreuses conditions qui ne devraient pas se produire, et/ou qui devraient au contraire briser le programme. Par exemple, une erreur de programmation (comme une division par zéro, une exception de pointeur nul), une mauvaise utilisation d'une API (IllegalStateException, OperationNotSupportedException), une panne matérielle, ou simplement une situation mineure qui n'est pas récupérable (perte de connexion à un serveur), ou une catastrophe naturelle :-) ; dans ces cas, la gestion normale est de laisser l'exception atteindre le bloc le plus externe de votre code qui affiche à l'utilisateur qu'une erreur imprévisible s'est produite et que l'application ne peut rien faire pour continuer. C'est une condition fatale, donc la seule chose que vous pouvez faire est de l'imprimer dans les journaux ou de l'afficher à l'utilisateur dans l'interface utilisateur. Dans ces cas, attraper l'exception est une erreur, car, après avoir attrapé l'exception, vous devez arrêter manuellement le programme pour éviter d'autres dommages ; il serait donc préférable de laisser une sorte d'exception "frapper le ventilateur" :)

Pour ces raisons, il y a certaines exceptions qui ne sont pas vérifiées dans le JRE : OutOfMemoryError (irrécupérable), NullPointerException (c'est un bogue qui doit être corrigé), ArrayIndexOutOfBoundsException (un autre exemple de bogue), et ainsi de suite.

Personnellement, je pense que les SQLException devraient également être décochées, car elles indiquent un bug dans le programme ou un problème de connexion à la base de données. Mais il y a de nombreux exemples où vous obtenez une exception que vous n'avez vraiment aucune idée de la façon de gérer (RemoteException).

La meilleure façon de gérer les exceptions est la suivante : si vous pouvez récupérer ou gérer l'exception, gérez-la. Sinon, laissez l'exception s'éteindre ; quelqu'un d'autre devra la gérer. Si vous êtes le dernier "quelqu'un d'autre" et que vous ne savez pas comment gérer une exception, affichez-la simplement (journal ou affichage dans l'interface utilisateur).

9voto

fge Points 40850
  1. vous n'avez pas besoin de déclarer les exceptions non vérifiées dans un fichier throws clause ; mais vous doit déclarer les exceptions contrôlées ;
  2. RuntimeException y Error et toutes leurs sous-classes ( IllegalArgumentException , StackOverflowError etc), sont des exceptions non vérifiées ; le fait que RuntimeException n'est pas vérifié, contrairement aux autres Throwable les sous-classes, c'est à dessein ;
  3. il n'existe pas d'"exceptions de compilation".

Plus généralement, on considère que les exceptions non vérifiées sont levées en cas d'erreurs de la JVM ou du programmeur. Une exception célèbre de ce type est NullPointerException souvent abrégé en NPE, qui est une sous-catégorie de RuntimeException et donc non contrôlé.

Une autre différence très importante entre les exceptions non vérifiées et les exceptions vérifiées est que dans un bloc try-catch, si vous voulez attraper des exceptions non vérifiées, vous devez les attraper explicitement .

Dernière remarque : si vous avez des classes d'exception E1 y E2 y E2 étend E1 puis attraper et/ou lancer E1 attrape ou lance également E2 . Cela vaut pour les exceptions vérifiées et non vérifiées. Cela a une implication sur catch blocs : si vous faites la différence entre attraper E2 y E1 vous doit attraper E2 d'abord.

Par exemple :

// IllegalArgumentException is unchecked, no need to declare it
public void illegal()
{
    throw new IllegalArgumentException("meh");
}

// IOException is a checked exception, it must be declared
public void ioerror()
    throws IOException
{
    throw new IOException("meh");
}

// Sample code using illegal(): if you want to catch IllegalArgumentException,
// you must do so explicitly. Not catching it is not considered an error
public void f()
{
    try {
        illegal();
    } catch (IllegalArgumentException e) { // Explicit catch!
        doSomething();
    }
}

J'espère que cela rend les choses plus claires...

7voto

JB Nizet Points 250258
  1. Non. Toutes les exceptions se produisent au moment de l'exécution. Les exceptions vérifiées sont des exceptions qui obligent l'appelant à les gérer ou à les déclarer. Elles sont généralement destinées à signaler des erreurs récupérables, qui ne sont pas causées par une erreur du programmeur (comme l'inexistence d'un fichier ou un problème de connectivité réseau). Les exceptions d'exécution sont généralement destinées à signaler des erreurs non récupérables. Elles n'obligent pas l'appelant à les gérer ou à les déclarer. Et beaucoup d'entre elles signalent effectivement des erreurs de programmation (comme NullPointerException).

  2. Car c'est ainsi que les JLS définissent une exception non vérifiée : une exception qui est ou étend RuntimeException, qui elle-même étend Exception. L'utilisation d'une racine d'héritage unique permet de gérer toutes les exceptions possibles dans une seule clause catch.

En ce qui concerne votre exemple : oui, la clause throws est obligatoire, puisque IOException est une exception vérifiée et que le code à l'intérieur de la méthode est susceptible d'en lancer une.

2voto

Marko Topolnik Points 77257

Le compilateur s'assure seulement qu'une méthode ne peut pas lancer une exception vérifiée si elle ne l'a pas déclarée. Il est généralement admis que cette vérification par le compilateur devrait être effectuée pour les exceptions dont l'occurrence est hors du contrôle du programmeur, comme les exemples que vous citez (connectivité de base de données, fichiers manquants, etc.). Les exceptions non vérifiées sont "censées ne pas se produire", le compilateur ne vous oblige donc pas à les déclarer.

Quant à la simulation IOException ou tout autre, c'est trivial :

throw new IOException();

Dans votre exemple, le prompt peut lancer un IOException c'est pourquoi il doit le déclarer. Cela n'a rien à voir avec la façon dont vous traitez l'exception au moment où vous appelez la méthode.

RuntimeException est une sous-classe de Exception pour faciliter la capture de toutes les exceptions avec une seule catch Exception clause. Cela aurait pu être conçu différemment ; la hiérarchie des classes d'exceptions de Java est un véritable fouillis.

1voto

Abhishekkumar Points 367

Si vous ne mettez pas la clause throws ici, cette erreur se produira.

ThrowsDemo.java:5 : exception non signalée java.io.IOException ; doit être attrapée ou déclarée pour être lancée. ou déclarée pour être levée return (char) System.in.read() ;

donc lance la clause dans nécessaire.

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