Voici un exemple simple de l'utilisation de l'exception :
class IntegerExceptionTest {
public static void main(String[] args) {
try {
throw new IntegerException(42);
} catch (IntegerException e) {
assert e.getValue() == 42;
}
}
}
Le corps de l'instruction TRy lance l'exception avec une valeur donnée, qui est rattrapé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é :
class ParametricException<T> extends Exception { // compile-time error
private final T value;
public ParametricException(T value) { this.value = value; }
public T getValue() { return value; }
}
Une tentative de compilation de ce qui précède signale une erreur :
% javac ParametricException.java
ParametricException.java:1: a generic class may not extend
java.lang.Throwable
class ParametricException<T> extends Exception { // compile-time error
^
1 error
Cette restriction est judicieuse car presque toutes les tentatives d'attraper une telle exception doivent échouer, car le type n'est pas réifiable. On pourrait s'attendre à ce qu'une utilisation typique de l'exception soit quelque chose comme ce qui suit :
class ParametricExceptionTest {
public static void main(String[] args) {
try {
throw new ParametricException<Integer>(42);
} catch (ParametricException<Integer> e) { // compile-time error
assert e.getValue()==42;
}
}
}
Ceci n'est pas autorisé, car le type dans la clause catch n'est pas réifiable. Au moment où nous écrivons ces lignes, le compilateur Sun signale une cascade d'erreurs de syntaxe dans un tel cas :
% javac ParametricExceptionTest.java
ParametricExceptionTest.java:5: <identifier> expected
} catch (ParametricException<Integer> e) {
^
ParametricExceptionTest.java:8: ')' expected
}
^
ParametricExceptionTest.java:9: '}' expected
}
^
3 errors
Comme les exceptions ne peuvent pas être paramétriques, la syntaxe est restreinte de sorte que le type doit être être écrit comme un identificateur, sans paramètre suivant.
2 votes
Les arguments de type générique sont remplacés par la borne supérieure, qui par défaut est Object. Si vous avez quelque chose comme List< ? extends A>, alors A est utilisé dans les fichiers de classe.
0 votes
Merci @Torsten. Je n'avais pas pensé à ce cas de figure auparavant.
2 votes
C'est une bonne question d'entretien, celle-là.
0 votes
@TorstenMarek : Si quelqu'un appelle
myList.get(i)
évidemmentget
renvoie toujours unObject
. Le compilateur insère-t-il un cast versA
afin de capturer une partie de la contrainte au moment de l'exécution ? Si ce n'est pas le cas, le PO a raison de dire qu'en fin de compte, tout se résume à ce qui suitObject
au moment de l'exécution. (Le fichier de classe contient certainement des métadonnées sur les éléments suivantsA
mais il ne s'agit que de métadonnées AFAIK).