Selon la spécification du langage Java , 3e édition:
Je souhaite comprendre pourquoi cette décision a été prise. Quel est le problème avec les exceptions génériques?
(Autant que je sache, les génériques sont simplement du sucre syntaxique au moment de la compilation, et ils seront traduits de Object
toute façon dans les .class
fichiers, donc déclarer efficacement une classe générique est comme si tout ce qu'elle contient était un Object
. Veuillez me corriger si je me trompe .)
java
generics
exception
language-design
Hosam Aly
la source
la source
myList.get(i)
,get
renvoie évidemment toujours unObject
. Le compilateur insère-t-il un cast pourA
capturer une partie de la contrainte au moment de l'exécution? Sinon, l'OP a raison de dire qu'en fin de compte, il se résume àObject
s au moment de l'exécution. (Le fichier de classe contient certainement des métadonnées surA
, mais ce ne sont que des métadonnées AFAIK.)Réponses:
Comme Mark l'a dit, les types ne sont pas réifiables, ce qui pose un problème dans le cas suivant:
Les deux
SomeException<Integer>
etSomeException<String>
sont effacés au même type, il n'y a aucun moyen pour la JVM de distinguer les instances d'exception, et donc aucun moyen de dire quelcatch
bloc doit être exécuté.la source
Voici un exemple simple d'utilisation de l'exception:
Le corps de l'instruction TRy lève l'exception avec une valeur donnée, qui est interceptée par la clause catch.
En revanche, la définition suivante d'une nouvelle exception est interdite, car elle crée un type paramétré:
Une tentative de compilation de ce qui précède signale une erreur:
Cette restriction est judicieuse car presque toute tentative pour intercepter une telle exception doit échouer, car le type n'est pas réifiable. On peut s'attendre à ce qu'une utilisation typique de l'exception ressemble à ce qui suit:
Cela n'est pas autorisé, car le type dans la clause catch n'est pas réifiable. Au moment d'écrire ces lignes, le compilateur Sun signale une cascade d'erreurs de syntaxe dans un tel cas:
Étant donné que les exceptions ne peuvent pas être paramétriques, la syntaxe est restreinte de sorte que le type doit être écrit en tant qu'identificateur, sans paramètre suivant.
la source
C'est essentiellement parce qu'il a été mal conçu.
Ce problème empêche une conception abstraite propre, par exemple
Le fait qu'une clause catch échouerait si les génériques ne sont pas réifiés n'est pas une excuse pour cela. Le compilateur pourrait simplement interdire les types génériques concrets qui étendent Throwable ou interdire les génériques à l'intérieur des clauses catch.
la source
EntityNotFoundException
. Mais cela rendrait les génériques inutiles.Les génériques sont vérifiés au moment de la compilation pour la correction du type. Les informations de type générique sont ensuite supprimées dans un processus appelé effacement de type . Par exemple,
List<Integer>
sera converti en type non génériqueList
.En raison de l' effacement du type , les paramètres de type ne peuvent pas être déterminés au moment de l'exécution.
Supposons que vous êtes autorisé à vous étendre
Throwable
comme ceci:Considérons maintenant le code suivant:
En raison de l' effacement du type , le runtime ne saura pas quel bloc catch exécuter.
C'est donc une erreur de compilation si une classe générique est une sous-classe directe ou indirecte de Throwable.
Source: problèmes d'effacement de type
la source
Je suppose que c'est parce qu'il n'y a aucun moyen de garantir le paramétrage. Considérez le code suivant:
Comme vous le notez, le paramétrage n'est que du sucre syntaxique. Cependant, le compilateur essaie de s'assurer que le paramétrage reste cohérent dans toutes les références à un objet dans la portée de compilation. Dans le cas d'une exception, le compilateur n'a aucun moyen de garantir que MyException est uniquement levée à partir d'une étendue qu'il traite.
la source