T
dans le
byte code
. Toutes les références à
T
sont remplacées par des références à
Object
lorsque ce type n'est pas connu. Lorsqu'il est connu, il est remplacé par son vrai type, et des
casts
sont insérés dans le code afin de préserver le vrai type. Lorsque l'on se retrouve dans une situation où deux méthodes doivent exister avec la même signature, mais des types de retour différents (ce qui est interdit en Java, mais qui peut arriver du fait du
type erasure
), des méthodes pont sont ajoutées.
Holder
suivante.
Exemple 27. Classe
Holder
public class Holder<T> { private T t ; public Holder(T t) { this.t = t ; } public T get() { return t ; } }
Integer
n'existe plus.
Exemple 28. Type erasure et cast - 1
boolean b1 = holder instanceof Holder<Integer> ; // Integer n’est pas pris en compte boolean b2 = holder instanceof Holder ; // équivalent à b2
Integer
ne sera pas présent dans le
byte code
, et que le
cast
ne se fera pas sur le type générique, mais plutôt sur
Holder
. De fait, c'est la deuxième ligne de code qui sera exécutée.
Exemple 29. Type erasure et cast - 2
Holder<Integer> h1 = (Holder<Integer>)object ; // warning à la compilation Holder<Integer> h2 = (Holder)object ; // h1 équivalent à h2
Exemple 30. Type erasure et cast - 3
Holder<Integer> h1 = ... ; // un premier holder Holder<String> h2 = ... ; // un second holder boolean b = h1.getClass() == h2.getClass() ; // b est vrai
String
et
Integer
ont été retirés du
byte code
. On se retrouve donc bien avec deux fois la même classe.
catch
.
Exemple 31. Utilisation illégale d'un type générique dans un
catch
try { ... } catch (T exception) { // illégal ici throw t ; // légal là }
T
ne se trouve pas dans le
byte code
.
Exemple 32. Constructions génériques illégales
public class Holder<T> { private T t ; public Holder(T t) { this.t = new T(t) ; // appel à ce constructeur illégal this.t = T.class.newInstance() ; // appel à T.class illégal } }
T
, alors il faut utiliser le pattern suivant.
Exemple 33. Construction générique correcte
public static <T> T newInstance(Class<T> clazz) { return clazz.newInstance() ; // gérer les exceptions InstantiationException et // IllegalAccessException }
Exemple 34. Membres statiques génériques illégaux
public class Singleton<T> { private static T t ; // déclaration illégale public static T newInstance(T t) { // déclaration illégale ... } }
equals(T)
devient une méthode
equals(Object)
définie au niveau de la classe
Object
. Cette déclaration est donc illégale.
Exemple 35. Méthode générique illégale
public class Holder<T> { public boolean equals(T t) { // déclaration illégale car collision après // application du type erasure ... ; } }