Historique de la question :
Les Generics Java ont été introduits dans Java 5 pour assurer un travail sûr avec les types de collections et de méthodes, mais ils ont été mis en œuvre avec un support de compatibilité ascendante avec le bytecode existant. Pour cela, le mécanisme d'effacement de type a été appliqué.
Problème :
Le compilateur Java exige une typage strict, mais pendant l'exécution, la JVM ne connaît pas les paramètres de typage, et de nombreuses anciennes classes et bibliothèques, y compris la bibliothèque des collections Java elle-même, fonctionnent avec des types "bruts" génériques (raw types). Sans compatibilité ascendante, il aurait été impossible de soutenir les développements existants.
Solution :
L'effacement de type est le processus de conversion des types paramétrés (génériques) en leurs versions "brutes", permettant à la JVM de fonctionner avec le bytecode existant sans modifications. Toutes les informations sur les paramètres de type sont supprimées lors de la compilation, et à la place, des objets de type Object (ou une contrainte si spécifiée via extends) sont utilisés.
Exemple de code :
List<String> stringList = new ArrayList<>(); stringList.add("hello"); String s = stringList.get(0); // get retourne Object, mais le compilateur insère un cast
Caractéristiques clés :
List<String>, List<Integer>, etc.Peut-on utiliser la surcharge de méthodes uniquement sur la base des paramètres des génériques ?
Non. En raison de l'effacement de type, le compilateur considère les méthodes avec les mêmes noms et différents paramètres de génériques comme identiques, car les paramètres seront effacés. Par exemple,
// Erreur de compilation ! void process(List<String> list) { } void process(List<Integer> list) { }
Peut-on créer un tableau de type générique ?
Non, directement. L'effacement de type n'autorise pas la JVM à stocker un tableau d'un type générique spécifique, par exemple,
List<String>[] array = new List<String>[10]; // Erreur de compilation
On peut contourner ce problème avec un tableau de types bruts, mais cela n'est pas sûr :
List<String>[] array = (List<String>[]) new List[10];
Peut-on vérifier le type générique à l'exécution via instanceof ?
Non, car l'information sur les paramètres est effacée. Vérification :
if (obj instanceof List<String>) { ... } // Erreur de compilation
Il est plus correct de ne vérifier que le type de base :
if (obj instanceof List) { ... }
Un programmeur crée un tableau de types paramétrés pour stocker des listes de différents paramètres. Au final, après un long temps d'exécution, une ClassCastException se produit lors de l'extraction d'un objet du tableau — la typage à l'exécution n'est pas assurée.
Avantages :
Inconvénients :
Au lieu des tableaux, on utilise des collections (par exemple, List<List<String>>), et toutes les vérifications de type sont déléguées au compilateur.
Avantages :
Inconvénients :