Pour compléter la réponse déjà très complète de Jon Skeet, vous devez réaliser le concept de effacement de type découle d'un besoin de compatibilité avec les versions précédentes de Java .
Initialement présentée à l'EclipseCon 2007 (qui n'est plus disponible), la compatibilité incluait ces points :
- Compatibilité des sources (souhaitable...)
- Compatibilité binaire (indispensable !)
- Compatibilité avec la migration
- Les programmes existants doivent continuer à fonctionner
- Les bibliothèques existantes doivent pouvoir utiliser des types génériques
- A avoir absolument !
Réponse originale :
D'où :
new ArrayList<String>() => new ArrayList()
Il existe des propositions pour une plus grande réification . Réifier étant "Considérer un concept abstrait comme réel", où les constructions linguistiques devraient être des concepts, et pas seulement du sucre syntaxique.
Je dois également mentionner le checkCollection
de Java 6, qui renvoie une vue dynamiquement sûre de la collection spécifiée. Toute tentative d'insertion d'un élément de type erroné entraînera un échec immédiat de la méthode ClassCastException
.
Le mécanisme des génériques dans le langage fournit une vérification des types à la compilation (statique), mais il est possible de contourner ce mécanisme avec des casts non vérifiés. .
En général, ce n'est pas un problème, car le compilateur émet des avertissements pour toutes ces opérations non vérifiées.
Il arrive cependant que la vérification statique des types ne suffise pas, par exemple :
- lorsqu'une collection est transmise à une bibliothèque tierce et qu'il est impératif que le code de la bibliothèque ne corrompe pas la collection en insérant un élément du mauvais type.
- un programme échoue avec un
ClassCastException
indiquant qu'un élément incorrectement typé a été placé dans une collection paramétrée. Malheureusement, l'exception peut survenir à tout moment après l'insertion de l'élément erroné, de sorte qu'elle ne fournit généralement que peu ou pas d'informations sur la source réelle du problème.
Mise à jour en juillet 2012, presque quatre ans plus tard :
Il est maintenant (2012) détaillé dans " Règles de compatibilité de la migration des API (test de signature) "
Le langage de programmation Java met en œuvre les génériques en utilisant l'effacement, ce qui garantit que les versions patrimoniales et génériques génèrent généralement des fichiers de classe identiques, à l'exception de certaines informations auxiliaires sur les types. La compatibilité binaire n'est pas rompue, car il est possible de remplacer un fichier de classe hérité par un fichier de classe générique sans modifier ni recompiler le code client.
Pour faciliter l'interfaçage avec du code hérité non générique, il est également possible d'utiliser l'effacement d'un type paramétré comme un type. Un tel type est appelé un type brut ( Spécification du langage Java 3/4.8 ). Le fait d'autoriser le type brut assure également une compatibilité ascendante pour le code source.
Selon cette dernière, les versions suivantes de l java.util.Iterator
sont rétrocompatibles tant au niveau du code binaire que du code source :
Class java.util.Iterator as it is defined in Java SE version 1.4:
public interface Iterator {
boolean hasNext();
Object next();
void remove();
}
Class java.util.Iterator as it is defined in Java SE version 5.0:
public interface Iterator<E> {
boolean hasNext();
E next();
void remove();
}