Las colecciones Java solo almacenan objetos, no tipos primitivos; Sin embargo, podemos almacenar las clases de contenedor.
¿Por qué esta restricción?
java
collections
types
primitive-types
JavaUser
fuente
fuente
class
, sino por la JVM. La instrucciónint i = 1
define un puntero a la instancia singleton del objeto que se defineint
en la JVM, establecido en el valor1
definido en algún lugar de la JVM. Sí, punteros en Java: la implementación del lenguaje simplemente lo abstrae de ti. Las primitivas no se pueden usar como genéricas porque el lenguaje predica todos los tipos genéricos deben ser del supertipoObject
, de ahí por qué seA<?>
compilaA<Object>
en tiempo de ejecución.Respuestas:
Fue una decisión de diseño de Java, y una que algunos consideran un error. Los contenedores quieren objetos y las primitivas no derivan de objetos.
Este es un lugar que los diseñadores de .NET aprendieron de la JVM e implementaron tipos de valores y genéricos, de modo que el boxeo se elimina en muchos casos. En CLR, los contenedores genéricos pueden almacenar tipos de valores 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. Siendo JVM lo que es, no es compatible con un objeto "no objeto". Los genéricos de Java le permiten pretender que no hay envoltorio, 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 se trata de detalles de implementación que se filtran al lenguaje. El 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 avise cuando se autoboxes. (Por lo que sé, puede que ahora, escribí esta respuesta en 2010).
Una buena explicación sobre SO sobre el boxeo: ¿Por qué algunos idiomas necesitan Boxing y Unboxing?
Y críticas a los genéricos de Java: ¿por qué algunos afirman que la implementación de genéricos de Java es mala?
En 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.
fuente
Object.ReferenceEquals
referencias de tipoObject
que identifiquen enteros en caja, pero no debería ser legal para pasar un valor entero]. El auto-desempaquetado de Java es, en mi humilde opinión, desagradable.Facilita la implementación. Dado que las primitivas de 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, los gastos generales para los envoltorios no son lo suficientemente importantes para que las personas se preocupen (y cuando tiene colecciones primitivas realmente grandes, es posible que desee dedicar el esfuerzo de considerar el uso / construcción de una estructura de datos especializada para ellos )
fuente
Es una combinación de dos hechos:
int
no es unObject
)List<?>
es realmente unaList<Object>
en tiempo de ejecución)Dado que ambos son ciertos, las colecciones genéricas de Java no pueden almacenar tipos primitivos directamente. Para mayor comodidad, se introduce el autoboxing para permitir que los tipos primitivos se encuadren automáticamente como tipos de referencia. Sin embargo, no se equivoque, las colecciones aún almacenan referencias de objetos independientemente.
¿Podría esto haberse evitado? Quizás.
int
es anObject
, entonces no hay necesidad de ningún tipo de cuadro.fuente
Existe el concepto de auto-boxing y auto-unboxing. Si intenta almacenar un
int
en unList<Integer>
compilador de Java lo convertirá automáticamente en unInteger
.fuente
No es realmente una restricción, ¿verdad?
Considere si desea crear una colección que almacena valores primitivos. ¿Cómo escribirías una colección que pueda almacenar int, float o char? Lo más probable es que termines con múltiples colecciones, por lo que necesitarás una lista de intlistas y una lista de charlas, 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, el polimorfismo, es muy poderosa y simplifica enormemente el diseño de bibliotecas.
fuente
Creo que podríamos ver progreso 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 de 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 .
Hace un tiempo también se publicó una comparación de mapas primitivos con el título: Descripción general de HashMap grande: JDK, FastUtil, Goldman Sachs, HPPC, Koloboke, Trove . La biblioteca GS Collections (Goldman Sachs) se migró a la Fundación Eclipse y ahora es Eclipse Collections.
fuente
La razón principal es la estrategia de diseño de Java. ++ 1) las colecciones requieren objetos para su manipulación y las primitivas no se derivan del objeto, por lo que esta puede ser la otra razón. 2) Los tipos de datos primitivos de Java no son tipos de referencia para ej. int no es un objeto.
Para superar:-
Tenemos el concepto de auto-boxing y auto-unboxing. así que si está tratando de almacenar tipos de datos primitivos, el compilador lo convertirá automáticamente en objeto de esa clase de datos primitivos.
fuente