objeto - ¿Por qué Java Collections no almacena directamente tipos de primitivos?
tipos primitivos java (6)
Las colecciones de Java solo almacenan Objetos, no tipos primitivos; sin embargo, podemos almacenar las clases de envoltura.
¿Por qué esta restricción?
Creo que podríamos ver progresos en este espacio en el JDK posiblemente en Java 10 basado en este JEP - http://openjdk.java.net/jeps/218 .
Si desea evitar las primitivas del boxeo en las colecciones de hoy, existen varias alternativas de terceros. Además de las opciones de terceros mencionadas anteriormente, también hay Eclipse Collections , FastUtil y Koloboke .
Una comparación de mapas primitivos también se publicó hace un tiempo con el título: Descripción general de HashMap: JDK, FastUtil, Goldman Sachs, HPPC, Koloboke, Trove . La biblioteca de GS Collections (Goldman Sachs) se migró a la Fundación Eclipse y ahora es Eclipse Collections.
Es una combinación de dos hechos:
- Los tipos primitivos de Java no son tipos de referencia (por ejemplo, un
int
no es unObject
) - Java hace genéricos utilizando borrado de tipo de tipos de referencia (por ejemplo, una
List<?>
Es realmente unaList<Object>
en tiempo de ejecución)
Como ambos son verdaderos, las colecciones Java genéricas no pueden almacenar tipos primitivos directamente. Para mayor comodidad, se introduce el autoboxing para permitir que los tipos primitivos se incluyan automáticamente en cuadros como tipos de referencia. Sin embargo, no se equivoque, las colecciones aún almacenan referencias de objetos.
¿Podría haberse evitado esto? Quizás.
- Si un
int
es unObject
, entonces no hay necesidad de ningún tipo de cuadro. - Si los genéricos no se hacen usando borrado de tipo, entonces las primitivas se podrían haber usado para los parámetros de tipo.
Existe el concepto de auto-boxing y auto-unboxing. Si intenta almacenar un int
en una List<Integer>
el compilador de Java lo convertirá automáticamente en un Integer
.
Fue una decisión de diseño de Java, y una que algunos consideran un error. Los contenedores quieren Objetos y primitivos no derivan de Objeto.
Este es un lugar que los diseñadores de .NET aprendieron de la JVM e implementaron tipos de valores y genéricos tales que el boxeo se elimina en muchos casos. En CLR, los contenedores genéricos pueden almacenar tipos de valor como parte de la estructura del contenedor subyacente.
Java optó por agregar soporte genérico al 100% en el compilador sin soporte de la JVM. La JVM es lo que es, no admite un objeto "no objeto". Los genéricos de Java le permiten pretender que no existe un contenedor, pero aún así paga el precio de rendimiento del boxeo. Esto es IMPORTANTE para ciertas clases de programas.
El boxeo es un compromiso técnico, y creo que es la filtración de detalles de la implementación en el lenguaje. Autoboxing es un buen azúcar sintáctico, pero sigue siendo una penalización de rendimiento. En todo caso, me gustaría que el compilador me advierta cuando se autocarta. (Por lo que sé, puede que ahora, escribí esta respuesta en 2010).
Una buena explicación sobre SO sobre boxeo: ¿Por qué algunos idiomas necesitan Boxeo y Unboxing?
Y crítica de los genéricos de Java: ¿por qué algunos afirman que la implementación de genéricos de Java es mala?
En la defensa de Java, es fácil mirar hacia atrás y criticar. La JVM ha resistido la prueba del tiempo y es un buen diseño en muchos aspectos.
Hace la implementación más fácil. Como las primitivas Java no se consideran Objetos, necesitaría crear una clase de colección separada para cada una de estas primitivas (sin código de plantilla para compartir).
Puede hacerlo, por supuesto, solo vea GNU Trove , Apache Commons Primitives o HPPC .
A menos que tenga colecciones realmente grandes, la sobrecarga de las envolturas no es lo suficientemente importante como para que a las personas les importe (y cuando realmente tienen grandes colecciones primitivas, es posible que desee dedicar el esfuerzo a utilizar / construir una estructura de datos especializada para ellas )
No es realmente una restricción, ¿verdad?
Considere si quería crear una colección que almacenara valores primitivos. ¿Cómo escribirías una colección que pueda almacenar int, float o char? Lo más probable es que termines con varias colecciones, por lo que necesitarás una intlist y una charlist, etc.
Aprovechando la naturaleza orientada a objetos de Java cuando escribe una clase de colección, puede almacenar cualquier objeto, por lo que solo necesita una clase de colección. Esta idea, polimorfismo, es muy poderosa y simplifica enormemente el diseño de las bibliotecas.