845 votes

Puis-je attraper plusieurs exceptions Java dans la même clause catch ?

En Java, je veux faire quelque chose comme ceci :

try {
    ...     
} catch (/* code to catch IllegalArgumentException, SecurityException, 
            IllegalAccessException, and NoSuchFieldException at the same time */) {
   someCode();
}

...au lieu de :

try {
    ...     
} catch (IllegalArgumentException e) {
    someCode();
} catch (SecurityException e) {
    someCode();
} catch (IllegalAccessException e) {
    someCode();
} catch (NoSuchFieldException e) {
    someCode();
}

Y a-t-il un moyen de le faire ?

1335voto

OscarRyz Points 82553

Cela a été possible depuis Java 7 . La syntaxe d'un bloc multi-catch est la suivante :

try { 
  ...
} catch (IllegalArgumentException | SecurityException | IllegalAccessException |
            NoSuchFieldException e) { 
  someCode();
}

N'oubliez pas, cependant, que si toutes les exceptions appartiennent à la même hiérarchie de classes, vous pouvez simplement attraper ce type d'exception de base.

Notez également que vous ne pouvez pas attraper les deux ExceptionA y ExceptionB dans le même bloc si ExceptionB est hérité, soit directement soit indirectement, de ExceptionA . Le compilateur se plaindra :

Alternatives in a multi-catch statement cannot be related by subclassing
  Alternative ExceptionB is a subclass of alternative ExceptionA

La solution consiste à n'inclure que l'exception de l'ancêtre dans la liste des exceptions, car les exceptions du type descendant seront également prises en compte.

93 votes

T.T - pourquoi redéfinir le bitwise or ( | ) ? Pourquoi ne pas utiliser une virgule, ou l'opérateur qui a une signification plus proche, le logical or ( || ) ?

14 votes

Peut-être qu'ils ont pensé que ça n'aurait plus d'importance après qu'ils aient trouvé la syntaxe pour limites multiples pour les génériques.

19 votes

Le signe XOR (I) n'est pas le même que le signe OR (||), A | B signifie soit A, soit B. mais pas les deux A || B signifie soit A ou B ou les deux donc pour les exceptions c'est soit exceptionA soit exceptionB mais pas les deux en même temps. c'est pourquoi ils ont utilisé le singe XOR au lieu de OR et vous pouvez le voir clairement quand l'exception est lancée si vous mettez 2 exceptions l'une d'entre elles est le sous-type d'une autre

119voto

user454322 Points 1172

Pas exactement avant Java 7 mais, je ferais quelque chose comme ça :

Java 6 et avant

try {
  //.....
} catch (Exception exc) {
  if (exc instanceof IllegalArgumentException || exc instanceof SecurityException || 
     exc instanceof IllegalAccessException || exc instanceof NoSuchFieldException ) {

     someCode();

  } else if (exc instanceof RuntimeException) {
     throw (RuntimeException) exc;     

  } else {
    throw new RuntimeException(exc);
  }

}

Java 7

try {
  //.....
} catch ( IllegalArgumentException | SecurityException |
         IllegalAccessException |NoSuchFieldException exc) {
  someCode();
}

12 votes

Notez que votre exemple en Java 6 ne permet pas au compilateur de savoir ce qui sera lancé à partir de quel endroit.

0 votes

Seulement s'il s'agit d'une instance de RuntimeException . J'ai mis à jour la réponse. =)

5 votes

Il s'agit d'une pratique plutôt mauvaise, du point de vue de la lisibilité.

31voto

duffymo Points 188155

Non, un par client avant Java 7.

Vous pouvez attraper une superclasse, comme java.lang.Exception, tant que vous effectuez la même action dans tous les cas.

try {
    // some code
} catch(Exception e) { //All exceptions are caught here as all are inheriting java.lang.Exception
    e.printStackTrace();
}

Mais ce n'est peut-être pas la meilleure pratique. Vous ne devriez attraper une exception que si vous avez une stratégie pour la traiter réellement - et enregistrer et relancer une exception n'est pas la "traiter". Si vous n'avez pas d'action corrective, il vaut mieux l'ajouter à la signature de la méthode et laisser remonter l'information à quelqu'un qui peut gérer la situation.

Avec le JDK 7 et les versions ultérieures, vous pouvez le faire :

try {
    ...     
} catch (IllegalArgumentException | SecurityException | IllegalAccessException | NoSuchFieldException e) {
    someCode();
}

23 votes

Puis-je vous demander de reformuler la partie concernant la capture de java.lang.Exception ? Je me rends compte qu'il s'agit d'un exemple, mais j'ai l'impression que certaines personnes pourraient lire cette réponse et se dire " oh, ok, je vais juste attraper l'exception alors ", alors que ce n'est probablement pas ce qu'elles veulent (ou devraient) faire.

2 votes

Je le savais, mais je ne veux pas le faire... Oh, eh bien, je suppose que je suis coincé avec 4 prises alors, jusqu'à la prochaine version de Java...

0 votes

@duffymo : Qu'est-ce qui ne va pas avec le logging et le rethrowing ? A part le fait que ça encombre le code, c'est équivalent à ne pas l'attraper, n'est-ce pas. Du point de vue de la stratégie générale de gestion des erreurs. Ce qui est mauvais, c'est la journalisation et no Jetez-le à nouveau.

26voto

ymene Points 2252

Dans Java 7, vous pouvez définir plusieurs clauses catch comme :

catch (IllegalArgumentException | SecurityException e)
{
    ...
}

21voto

Michael Shopsin Points 830

S'il existe une hiérarchie d'exceptions, vous pouvez utiliser la classe de base pour attraper toutes les sous-classes d'exceptions. Dans le cas dégénéré, vous pouvez attraper tous Les exceptions Java avec :

try {
   ...
} catch (Exception e) {
   someCode();
}

Dans un cas plus courant, si RepositoryException est la classe de base et PathNotFoundException une classe dérivée, alors.. :

try {
   ...
} catch (RepositoryException re) {
   someCode();
} catch (Exception e) {
   someCode();
}

Le code ci-dessus attrapera RepositoryException et PathNotFoundException pour un type de traitement des exceptions et toutes les autres exceptions seront regroupées. Depuis Java 7, selon la réponse de @OscarRyz ci-dessus :

try { 
  ...
} catch( IOException | SQLException ex ) { 
  ...
}

7 votes

En fait, les clauses catch sont traitées dans l'ordre. Ainsi, si vous placez une classe d'exception parent avant une classe enfant, elle ne sera jamais appelée, par exemple : try { ... } catch (Exception e) { someCode() ; } catch (RepositoryException re) { // jamais atteint }

4 votes

En fait, précisément parce qu'il ne peut jamais être atteint, un tel code ne se compile même pas.

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