Bene, la motivazione (retrocompatibilità) è sia un vantaggio che uno svantaggio. È uno svantaggio perché tutti preferiremmo avere tipi riutilizzabili, ma il prezzo da pagare era alto. Considera le scelte di progettazione in C #. Hanno tipi riutilizzabili, ma ora hanno API duplicate. Quindi, immagina un'API Java in cui avevamo anche API duplicate per ogni classe con parametri. Ora immagina di portare 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 riutilizzabili!
Quindi, la motivazione principale è stata "l'evoluzione, non la rivoluzione". E logicamente, ogni decisione ha dei compromessi.
Oltre agli altri svantaggi menzionati, potremmo anche aggiungere il fatto che la cancellazione del tipo può essere difficile da ragionare al momento della compilazione, poiché non è evidente che alcuni tipi verranno rimossi e questo porta a errori molto strani e difficili da trovare.
L'esistenza di metodi bridge (questo metodo generato sintatticamente dal compilatore per mantenere la compatibilità binaria) può anche essere vista come uno svantaggio. E questi possono essere precisamente uno dei motivi degli errori che ho citato nel paragrafo precedente.
I principali svantaggi derivano dal fatto già evidente che esiste una singola classe e non più classi per tipi generici. Come altro esempio, considera che il sovraccarico di un metodo con la stessa classe generica non riesce in Java:
public void doSomething(List<One>);
public void doSomething(List<Two>);
Qualcosa che potrebbe essere visto come uno svantaggio di tipi riutilizzabili (almeno in C #) è il fatto che causano l' esplosione del codice . Ad esempio List<int>è una classe e a List<double>è un'altra totalmente diversa, in quanto è a List<string>e a List<MyType>. Quindi le classi devono essere definite in fase di esecuzione, causando un'esplosione di classi e consumando risorse preziose mentre vengono generate.
Per quanto riguarda il fatto che non è possibile definire un new T()in Java, menzionato in un'altra risposta, è anche interessante considerare che questa 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é il nuovo T () non è possibile in Java , di Alex Buckley).
Ts, ottieni solo una copia delClass<T>codice per tutti iTs; più una copia aggiuntiva per ogni tipo di valoreTeffettivamente utilizzato.