En el muy alto nivel, sé que tenemos que "envolver" los tipos de datos primitivos, como int y char, utilizando sus respectivas clases contenedoras para usarlos dentro de las colecciones Java. Me gustaría entender cómo funcionan las colecciones Java. en el nivel bajo, preguntando: "¿por qué tenemos que envolver los tipos de datos primitivos como objetos para poder usarlos en las colecciones?" Le agradezco de antemano su ayuda.Java: ¿Por qué son necesarias las clases de contenedor?
Respuesta
En el nivel de la máquina virtual, es porque los tipos primitivos se representan de forma muy diferente en la memoria en comparación con los tipos de referencia como java.lang.Object y sus tipos derivados. Primitive int en Java, por ejemplo, tiene solo 4 bytes en la memoria, mientras que un objeto ocupa al menos 8 bytes por sí mismo, más otros 4 bytes para hacer referencia a él. Tal diseño es un simple reflejo del hecho de que las CPU pueden tratar tipos primitivos de manera mucho más eficiente.
Así que una respuesta a su pregunta "por qué son necesarios los tipos de envoltura" se debe a la mejora del rendimiento que permite.
Pero para los programadores, tal distinción agrega una carga cognitiva indeseable (por ejemplo, no se puede usar int y float en colecciones). De hecho, es posible hacer un diseño de lenguaje ocultando esa distinción --- muchos lenguajes de scripting haz esto, y CLR hace eso. A partir de 1.5, Java también lo hace. Esto se logra al permitir que el compilador inserte silenciosamente la conversión necesaria entre la representación primitiva y la representación de Objeto (que comúnmente se conoce como boxeo/unboxing).)
Así que otra respuesta a su pregunta es: "no, no la necesitamos", porque el compilador lo hace automáticamente, y en cierta medida puede olvidar lo que sucede detrás de la escena.
¿Puede explicar cómo JVM almacena los tipos primitivos y los tipos de referencia en la memoria? –
@Midnight Blue - Lea la primera respuesta (por Jon Skeet) aquí: http://stackoverflow.com/questions/2099695/java-array-is-stored-in-stack-or-heap. Explica más sobre cómo se almacenan las cosas en la JVM y cuándo. –
@Justin N. - Gracias por el enlace –
Debido a que las colecciones de Java solo pueden almacenar referencias a objetos (por lo que debe colocar primitivas en el cuadro para almacenarlas en colecciones).
Lea este artículo breve en Autoboxing para obtener más información.
Si desea que los detalles Nitty Gritty, que prácticamente se reduce a lo siguiente:
Primitives locales se almacenan en la pila. Las colecciones almacenan sus valores a través de una referencia a la ubicación de memoria de un Objeto en el Heap. Para obtener esa referencia para una primitiva local, tiene que insertar el valor (tomar el valor en la pila y envolverlo para almacenarlo en el montón).
No se puede hacer referencia a los tipos de datos primitivos como direcciones de memoria. Es por eso que necesitamos envolturas que sirvan como marcadores de posición para valores primitivos. Estos valores pueden ser mutados y accedidos, reorganizados, ordenados o aleatorizados.
¿Eh? Java no tiene punteros. – BalusC
Usted escribió: "Estos valores pueden ser mutados". Esto no es cierto para las envolturas de objetos primitivos en Java. Todos son inmutables. – Asaph
Una referencia básicamente es un puntero, solo un poco más restrictivo. En mi opinión, deberían haberlo llamado puntero en lugar de referencia, ya que el término "referencia" es muy engañoso. – helpermethod
Ver Boxing and unboxing: when does it come up?
Es para C#, pero el mismo concepto se aplica a Java. Y John Skeet escribió la respuesta.
Bueno, la razón es porque las colecciones de Java no diferencian entre primitivo y Objeto. Los procesa todos como Objeto y, por lo tanto, necesitará un contenedor. Puedes construir fácilmente tu propia clase de colección que no necesita envoltorio, pero al final, tendrás que compilar una para cada tipo char, int, float, double, etc. multiplica por los tipos de colecciones (Set, Map, Lista, + su implementación).
¿Te imaginas lo aburrido que es eso?
Y la realidad es que el rendimiento que aporta el uso de envoltorios es casi insignificante para la mayoría de las aplicaciones. Sin embargo, si necesita un rendimiento muy alto, algunas bibliotecas para colecciones primitivas también están disponibles (por ejemplo, http://www.joda.org/joda-primitives/)
Las colecciones se diferencian muy bien: funcionan bastante bien con los objetos y te abofetean con errores de compilación si pruebas con primitivos Java. –
Para almacenar los valores del tipo primitivo en clases de recopilación, se requiere clasificación de Contenedor.
Colección utiliza genéricos como base. The Collection Framework está diseñado para recopilar, almacenar y manipular los datos de cualquier clase. Entonces usa un tipo genérico. Al usar Generics, es capaz de almacenar los datos de CUALQUIER CLASE cuyo nombre especifique en su declaración.
Ahora tenemos varios escenarios en los que queremos almacenar los datos primitivos de la misma manera en que funciona la colección. No tenemos forma de almacenar datos primitivos usando clases de Colección como ArrayList, HashSet, etc. porque las clases de Colección solo pueden almacenar objetos. Entonces, para almacenar tipos primitivos en Collection, se nos proporcionan clases de contenedor.
Las clases de envoltorio proporcionan métodos útiles relacionados con los tipos de datos correspondientes que puede utilizar en ciertos casos.
Un ejemplo simple. Considere esto,
Integer x=new Integer(10);
//to get the byte value of 10
x.byteValue();
//but you can't do this,
int x=10;
x.byteValue(); //Wrong!
¿Puede entender el punto?
Si se sabe que una variable contiene un patrón de bits específico que representa null
o información que puede usarse para localizar un encabezado de objeto Java Virtual Machine, y si el método para leer un encabezado de objeto dado una referencia atrapará si dado el patrón de bits asociado con null
, la JVM puede acceder al objeto identificado por la variable en el supuesto de que exista uno. Si una variable podría contener algo que no era una referencia válida pero no era el patrón de bits específico null
, cualquier código que intentara usar esa variable tendría que verificar primero si identificaba un objeto. Eso ralentizaría mucho la JVM.
Si Object
deriva de Anything
, y los objetos clase derivada de Object
, pero primitivos heredados de una clase diferente derivado de Anything
, a continuación, en una aplicación de 64 bits que podría ser práctico para decir que aproximadamente 3/4 de la posible bits los patrones representarían double
valores por debajo de 2^512, 1/8 de ellos para representar long
valores en el rango +/- 1,152,921,504,606,846,975, algunos miles de millones para representar cualquier valor posible de cualquier primitve y 1/256 para identificar objetos. Muchos tipos de operaciones en cosas del tipo Anything
serían más lentas que con el tipo Object
, pero tales operaciones no serían terriblemente frecuentes; la mayoría del código terminaría fundiendo Anything
en algún tipo más específico antes de intentar trabajar con él; el tipo real almacenado en Anything
debería verificarse antes del lanzamiento, pero no después de que se haya realizado el lanzamiento. Sin una distinción entre una variable que contiene una referencia a un tipo de montón, sin embargo, frente a una que tenga "nada", no habría forma de evitar que la sobrecarga se extienda considerablemente más allá de lo que debería o debería.
Al igual que la clase String, los Wrappers proporcionan funcionalidad adicional y permiten al programador hacer un poco más con el proceso de almacenamiento de datos. Así que en la misma forma de utilizar la clase String como ....
String uglyString = "fUbAr"; String myStr = uglyString.toLower();
así también, que pueden con la envoltura. Idea similar
Esto se suma a la cuestión de tipeo de colecciones/genéricos mencionados anteriormente por Bharat.
Lea todas las respuestas, pero ninguna de ellas realmente lo explica simplemente en términos sencillos.
A envoltura envolturas de clase (encierra) alrededor de un tipo de datos (puede ser cualquier tipo de datos primitivos como int, char, byte, de largo) y lo convierte en un objeto.
Estas son algunas de las razones por qué se necesitan clases de contenedor:
- Permite
null
valores. - Puede ser utilizado en la recogida tal como
List
,Map
, etc. - Se puede utilizar en métodos que acepta argumentos de
Object
tipo. se pueden crear objetos utilizando como
new ClassName()
al igual que otros objetos:Integer wrapperInt = new Integer("10");
- pone a disposición todas las funciones que
Object
clase tiene comoclone()
,equals()
,hashCode()
, etc.toString()
clases Wrapper se puede crear de dos maneras:
Usando constructor:
Integer i = new Integer("1"); //new object is created
Usando
valueOf()
operadores estáticas:Integer i = Integer.valueOf("100"); //100 is stored in variable
Se aconseja utilizar la segunda forma de crear clases contenedoras, ya que toma menos memoria como un nuevo objeto es no creado.
porque int no pertenece a ninguna clase. convertimos el tipo de datos (int) al objeto (Interger)
- 1. ¿Por qué son necesarias las declaraciones anticipadas?
- 2. ¿Qué clases son absolutamente necesarias para ejecutar una VM Java?
- 3. Por qué son necesarias las propiedades de automatización en WPF
- 4. ¿Por qué son necesarias las entidades de caracteres HTML?
- 5. ¿Por qué hay clases de contenedor en Java?
- 6. ¿Son necesarias las interfaces en JavaScript?
- 7. ¿Las clases de Java son objetos?
- 8. ¿Por qué todas las clases anónimas son implícitamente finales?
- 9. ¿Qué son las clases S1 y S2?
- 10. API de colecciones de Java: ¿por qué las clases [Lista | Establecer | Mapa] no son modificables?
- 11. ¿Por qué Android prefiere las clases estáticas
- 12. ¿Las clases internas son livianas?
- 13. ¿Las clases de envoltura de Java son realmente inmutables?
- 14. ¿Qué se entiende por clases en sí mismas son objetos?
- 15. En Java, ¿por qué las clases de excepción deben estar disponibles para el cargador de clases antes de que sean necesarias?
- 16. ¿Por qué las enumeraciones de Java no son clonables?
- 17. ¿Por qué las clases abstractas en Java tienen constructores?
- 18. ¿Por qué las interfaces no son [Serializable]?
- 19. Cuando tenemos clases de envoltorios, ¿por qué las primitivas son compatibles?
- 20. ¿Qué características de lenguaje son necesarias para las secuencias de comandos del juego?
- 21. ¿Por qué son costosas las sincronizaciones en Java?
- 22. ¿Las clases de ByteBuffer/IntBuffer/ShortBuffer Java son rápidas?
- 23. ¿Las clases anónimas en "caché" de Java son?
- 24. ¿Por qué las clases de Java no heredan las anotaciones de las interfaces implementadas?
- 25. ¿Qué son las cookies firmadas y por qué son útiles?
- 26. ¿Son necesarias restricciones únicas en el DB?
- 27. ¿Por qué Eclipse no actualiza las clases?
- 28. ¿Todas las clases finales son inmutables?
- 29. ¿Qué son las llamadas en java?
- 30. ¿Por qué las clases no están selladas por defecto?
posible duplicado de [¿Por qué hay clases contenedoras en Java?] (Http://stackoverflow.com/questions/3579035/why-are-there-wrapper-classes -in-java) – nbro