Pourquoi Java multi-catch ne peut-il pas traiter des types liés par sous-classement?

Voici un morceau de code qui ne doit pas être compilé:

void multiCatch() { try { throwIOFile(); } // FileNotFoundException extends IOException, hence this // does not comstack ("alternatives" related by sub classing): catch (IOException | FileNotFoundException e) { } } void throwIOFile() throws IOException, FileNotFoundException {} 

Tout fonctionne à merveille si les types d’exception n’avaient pas été associés par sous-classement. Si vous SQLException IOException dans mon extrait de code, par exemple, SQLException , cela fonctionne. La spécification se lit comme suit:

C’est une erreur de compilation si une union de types contient deux alternatives Di et Dj (i ≠ j) où Di est un sous-type de Dj.

Je ne peux pas comprendre la raison derrière cela. Certes, la capture multiple dans mon exemple est complètement redondante car je pourrais tout aussi bien attraper une IOException . Mais quel serait le mal à rendre mon extrait de code légal? Il doit sûrement y avoir un préjudice pour qu’une pratique devienne illégale?

La spec discute que

Une clause multi-sockets peut être considérée comme une séquence de clauses uni-captures

donc votre code est un peu comme

  try { throwIOFile(); } catch (IOException e) { } catch (FileNotFoundException e) { } // error 

Ceci est également rejeté par javac. Dans ce cas, l’erreur est justifiée car la 2e clause est inaccessible.


Cependant, je ne pense pas que le type d’union devrait être interdit. Ce devrait être au mieux un avertissement.

Avoir des sous-classes d’une exception donnée dans la même capture n’a tout simplement aucun sens et cela crée de la confusion, car vous allez quand même entrer la capture, peu importe les sous-classes que vous spécifiez. Par exemple, pourquoi allez-vous écrire

 catch (IOException | FileNotFoundException e) 

si

 catch (IOException e) 

aura exactement le même comportement? C’est simplement déroutant.

Mais quel serait le mal à rendre mon extrait de code légal? Il doit sûrement y avoir un préjudice pour qu’une pratique devienne illégale?

C’est un code déroutant – vous pouvez le simplifier en attrapant simplement IOException , alors qu’il semble que vous ayez vraiment besoin d’attraper les deux séparément.

Je ne peux pas affirmer avec certitude que c’est la raison, mais c’est la raison que j’utiliserais pour la justifier. Empêchez les développeurs d’abuser d’une fonctionnalité alors qu’ils ne peuvent écrire que du code plus simple.