Eh bien, la motivation (compatibilité descendante) est à la fois un avantage et un inconvénient. C'est un inconvénient car nous préférerions tous avoir des types réifiables, mais le prix à payer était élevé. Considérez les choix de conception en C #. Ils ont des types réifiables, mais maintenant ils ont des API en double. Imaginez donc une API Java où nous avions également des API en double pour chaque classe paramétrée. Maintenant, imaginez-vous porter des milliers de lignes de code des classes héritées vers les nouvelles classes génériques. Maintenant, qui ne considérerait pas les API en double comme un inconvénient? Mais bon, ils ont des types réifiables!
Ainsi, la motivation principale était "l'évolution, pas la révolution". Et logiquement, chaque décision a des compromis.
Outre les autres inconvénients mentionnés, nous pourrions également ajouter le fait que l'effacement de type peut être difficile à raisonner au moment de la compilation, car il n'est pas évident que certains types seront supprimés, ce qui conduit à des erreurs très étranges et difficiles à trouver.
L'existence de méthodes de pontage (ce compilateur de méthodes générées syntaxiquement pour conserver la compatibilité binaire) peut également être considérée comme un inconvénient. Et cela peut être précisément l'une des raisons des erreurs que j'ai mentionnées dans le paragraphe précédent.
Les inconvénients majeurs découlent du fait déjà évident qu'il existe une seule classe et non plusieurs classes pour les types génériques. Comme autre exemple, considérons que la surcharge d'une méthode avec la même classe générique échoue en Java:
public void doSomething(List<One>);
public void doSomething(List<Two>);
Quelque chose qui pourrait être considéré comme un inconvénient des types réifiables (au moins en C #) est le fait qu'ils provoquent une explosion de code . Par exemple, List<int>est une classe, et a List<double>est une autre totalement différente, car c'est un List<string>et un List<MyType>. Les classes doivent donc être définies au moment de l'exécution, ce qui provoque une explosion des classes et consomme des ressources précieuses lors de leur génération.
Concernant le fait qu'il n'est pas possible de définir un new T()en Java, mentionné dans une autre réponse, il est également intéressant de considérer que ce n'est pas seulement une question d'effacement de type. Cela nécessite également l'existence d'un constructeur par défaut, c'est pourquoi C # nécessite pour cela une "nouvelle contrainte". (Voir Pourquoi le nouveau T () n'est pas possible en Java , par Alex Buckley).
Ts, vous obtenez une seule copie duClass<T>code pour tous lesTs; plus une copie supplémentaire pour chaque type de valeurTréellement utilisé.