Nun, die Motivation (Abwärtskompatibilität) ist sowohl ein Vorteil als auch ein Nachteil. Es ist ein Nachteil, weil wir alle lieber reifizierbare Typen hätten, aber der zu zahlende Preis war hoch. Berücksichtigen Sie die Entwurfsoptionen in C #. Sie haben reifizierbare Typen, aber jetzt haben sie doppelte APIs. Stellen Sie sich also eine Java-API vor, bei der wir auch doppelte APIs für jede parametrisierte Klasse hatten. Stellen Sie sich nun vor, Sie portieren Tausende von Codezeilen von Legacy-Klassen auf die neuen generischen Klassen. Wer würde doppelte APIs nicht als Nachteil betrachten? Aber hey, sie haben reifizierbare Typen!
Die Hauptmotivation war also "Evolution, nicht Revolution". Und logischerweise hat jede Entscheidung Kompromisse.
Neben den anderen genannten Nachteilen können wir auch die Tatsache hinzufügen, dass das Löschen von Typen zum Zeitpunkt der Kompilierung schwierig zu begründen sein kann, da nicht ersichtlich ist, dass bestimmte Typen entfernt werden, und dies zu sehr seltsamen und schwer zu findenden Fehlern führt.
Die Existenz von Bridge-Methoden (diese vom Compiler syntaktisch generierten Methoden zur Wahrung der Binärkompatibilität) kann ebenfalls als Nachteil angesehen werden. Und dies kann genau einer der Gründe für Fehler sein, die ich im vorherigen Absatz erwähnt habe.
Hauptnachteile ergeben sich aus der bereits offensichtlichen Tatsache, dass es für generische Typen eine einzelne Klasse und nicht mehrere Klassen gibt. Als weiteres Beispiel gilt, dass das Überladen einer Methode mit derselben generischen Klasse in Java fehlschlägt:
public void doSomething(List<One>);
public void doSomething(List<Two>);
Etwas , das als Nachteil reifiable Typen (zumindest in C #) ist die Tatsache , dass sie Ursache gesehen werden könnte Code Explosion . Zum Beispiel List<int>ist eine Klasse und a List<double>ist eine andere völlig anders, wie es a List<string>und a ist List<MyType>. Daher müssen Klassen zur Laufzeit definiert werden, was zu einer Explosion von Klassen führt und wertvolle Ressourcen verbraucht, während sie generiert werden.
In Anbetracht der Tatsache, dass es nicht möglich ist, ein new T()in Java zu definieren , was in einer anderen Antwort erwähnt wird, ist es auch interessant zu berücksichtigen, dass dies nicht nur eine Frage der Typlöschung ist. Es erfordert auch die Existenz eines Standardkonstruktors, weshalb C # hierfür eine "neue Einschränkung" erfordert. (Siehe Warum neues T () in Java nicht möglich ist , von Alex Buckley).
Tnur eine Kopie desClass<T>Codes für alleTs erhalten. plus eine zusätzliche Kopie für jeden WerttypTtatsächlich verwendet wird .