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.