Bene, la motivazione (retrocompatibilità) è sia un vantaggio che uno svantaggio. È uno svantaggio perché preferiremmo tutti avere tipi reifiable, ma il prezzo da pagare era alto. Considera le scelte di progettazione in C #. Hanno tipi reificabili, ma ora hanno API duplicate. Quindi, immagina un'API Java in cui disponiamo anche di API duplicate per ogni classe parametrizzata. Ora immagina di trasferire migliaia di righe di codice dalle classi legacy alle nuove classi generiche. Ora, chi non considererebbe le API duplicate uno svantaggio? Ma hey, hanno tipi reificabili!
Quindi, la motivazione principale era "evoluzione, non rivoluzione". E logicamente, ogni decisione ha dei compromessi.
Oltre agli altri svantaggi menzionati, potremmo anche aggiungere il fatto che la cancellazione dei tipi può essere difficile da ragionare in fase di compilazione, dal momento che non è evidente che alcuni tipi verranno rimossi, e ciò porta a risultati molto bizzarri e difficili da trovare errori.
L'esistenza di metodi bridge (questo metodo generato dal sintetizzatore per mantenere la compatibilità binaria) può anche essere visto come uno svantaggio. E questi possono essere proprio uno dei motivi degli errori che ho menzionato nel paragrafo precedente.
I principali svantaggi derivano dal fatto già ovvio che esiste una singola classe e non più classi per tipi generici. Come altro esempio, consideriamo che l'overload di un metodo con la stessa classe generica non funziona in Java:
public void doSomething(List<One>);
public void doSomething(List<Two>);
Qualcosa che potrebbe essere visto come uno svantaggio di tipi reifiable (almeno in C #) è il fatto che causano esplosione del codice . Ad esempio List<int>
è una classe, e List<double>
è un'altra completamente diversa, in quanto è un List<string>
e un List<MyType>
. Quindi le classi devono essere definite in fase di esecuzione, causando un'esplosione di classi e il consumo di risorse preziose mentre vengono generate.
Riguardo al fatto che non è possibile definire un new T()
in Java, menzionato in un'altra risposta, è anche interessante considerare che questo non è solo una questione di cancellazione del tipo. Richiede anche l'esistenza di un costruttore predefinito, ecco perché C # richiede un "nuovo vincolo" per questo. (Vedi Perché la nuova T () non è possibile in Java , di Alex Buckley).