Bueno, la motivación (compatibilidad con versiones anteriores) es tanto una ventaja como una desventaja. Es una desventaja porque todos preferiríamos tener tipos reificables, pero el precio a pagar era alto. Considere las opciones de diseño en C #. Tienen tipos reificables, pero ahora tienen API duplicadas. Entonces, imagine una API Java donde también tenemos API duplicadas para cada clase parametrizada. Ahora, imagínese portando miles de líneas de código de clases heredadas a las nuevas clases genéricas. Ahora, ¿quién no consideraría una API duplicada una desventaja? Pero bueno, ¡tienen tipos reificables!
Entonces, la principal motivación fue "evolución, no revolución". Y lógicamente, cada decisión tiene compensaciones.
Además de las otras desventajas mencionadas, también podríamos agregar el hecho de que la eliminación de tipos puede ser difícil de razonar en el momento de la compilación, ya que no es evidente que se eliminen ciertos tipos, y esto conduce a errores muy extraños y difíciles de encontrar.
La existencia de métodos puente (este compilador genera métodos sintácticamente para mantener la compatibilidad binaria) también puede verse como una desventaja. Y estos pueden ser precisamente uno de los motivos de los errores que mencioné en el párrafo anterior.
Las principales desventajas se derivan del hecho ya obvio de que hay una sola clase y no múltiples clases para los tipos genéricos. Como otro ejemplo, considere que sobrecargar un método con la misma clase genérica falla en Java:
public void doSomething(List<One>);
public void doSomething(List<Two>);
Algo que podría verse como una desventaja de los tipos reificables (al menos en C #) es el hecho de que causan la explosión del código . Por ejemplo, List<int>
es una clase, y a List<double>
es otra totalmente diferente, ya que es a List<string>
y a List<MyType>
. Por lo tanto, las clases deben definirse en tiempo de ejecución, lo que provoca una explosión de clases y consume recursos valiosos mientras se generan.
Con respecto al hecho de que no es posible definir un new T()
en Java, mencionado en otra respuesta, también es interesante considerar que esto no es solo una cuestión de borrado de tipo. También requiere la existencia de un constructor predeterminado, por eso C # requiere una "nueva restricción" para esto. (Consulte Por qué el nuevo T () no es posible en Java , por Alex Buckley).
T
s, solo se obtiene una copia delClass<T>
código para todos losT
s; más una copia adicional para cada tipo de valorT
realmente utilizado.