Bem, a motivação (compatibilidade com versões anteriores) é uma vantagem e uma desvantagem. É uma desvantagem, porque todos nós preferimos ter tipos reificáveis, mas o preço a pagar foi alto. Considere as opções de design em C #. Eles têm tipos reificáveis, mas agora eles têm APIs duplicadas. Então, imagine uma API Java em que também tivemos APIs duplicadas para cada classe parametrizada. Agora, imagine-se portando milhares de linhas de código das classes herdadas para as novas classes genéricas. Agora, quem não consideraria as APIs duplicadas uma desvantagem? Mas ei, eles têm tipos reificáveis!
Portanto, a principal motivação foi "evolução, não revolução". E logicamente, toda decisão tem trocas.
Além das outras desvantagens mencionadas, também podemos acrescentar o fato de que o apagamento de tipo pode ser difícil de raciocinar no momento da compilação, pois não é evidente que determinados tipos serão removidos e isso leva a erros muito estranhos e difíceis de encontrar.
A existência de métodos de ponte ( métodos compilados gerados sintaticamente para manter a compatibilidade binária) também pode ser vista como desvantagem. E essas podem ser precisamente uma das razões dos erros que mencionei no parágrafo anterior.
As principais desvantagens decorrem do fato já óbvio de que existe uma única classe e não várias para tipos genéricos. Como outro exemplo, considere que a sobrecarga de um método com a mesma classe genérica falha em Java:
public void doSomething(List<One>);
public void doSomething(List<Two>);
Algo que pode ser visto como uma desvantagem de tipos reificáveis (pelo menos em C #) é o fato de eles causarem explosão de código . Por exemplo, List<int>
é uma classe e a List<double>
é outra totalmente diferente, pois é a List<string>
e a List<MyType>
. Portanto, as classes precisam ser definidas em tempo de execução, causando uma explosão de classes e consumindo recursos valiosos enquanto são gerados.
Quanto ao fato de não ser possível definir a new T()
em Java, mencionado em outra resposta, também é interessante considerar que isso não é apenas uma questão de apagamento de tipo. Também requer a existência de um construtor padrão, por isso o C # requer uma "nova restrição" para isso. (Veja Por que o novo T () não é possível em Java , por Alex Buckley).
T
s, você recebe apenas uma cópia doClass<T>
código para todos osT
s; além de uma cópia adicional para cada tipo de valorT
realmente usado.