Je pense que d'autres réponses l'ont dit dans une certaine mesure, mais pas très clairement. L'un des problèmes avec les génériques est la perte des types génériques au cours du processus de réflexion. Donc par exemple:
List<String> arr = new ArrayList<String>();
assertTrue( ArrayList.class, arr.getClass() );
TypeVarible[] types = arr.getClass().getTypedVariables();
Malheureusement, les types retournés ne peuvent pas vous dire que les types génériques d'arr sont String. C'est une différence subtile, mais c'est important. Puisque arr est créé à l'exécution, les types génériques sont effacés à l'exécution, de sorte que vous ne pouvez pas vous en assurer. Comme certains l'ont dit, cela ArrayList<Integer>
ressemble au ArrayList<String>
point de vue de la réflexion.
Cela n’a peut-être pas d'importance pour l'utilisateur de Generics, mais supposons que nous voulions créer un cadre sophistiqué qui utilise la réflexion pour déterminer de façon compliquée la manière dont l'utilisateur a déclaré les types génériques concrets d'une instance.
Factory<MySpecialObject> factory = new Factory<MySpecialObject>();
MySpecialObject obj = factory.create();
Disons que nous voulions qu'une usine générique crée une instance de MySpecialObject
car c'est le type générique concret que nous avons déclaré pour cette instance. La classe Well Factory ne peut pas s’interroger sur le type concret déclaré pour cette instance car Java les a effacés.
Vous pouvez le faire avec les génériques .Net, car au moment de l'exécution, l'objet sait que ce sont des types génériques, car le compilateur l'a intégré au binaire. Avec des effacements, Java ne peut pas faire cela.