Cada objeto no cadena no-array almacenado en el montón contiene una cabecera de 8 ó 16 bytes (tamaños para 32/sistemas de 64 bits), seguido por el contenido de ese del público objeto y campos privados Las matrices y las cadenas tienen el encabezado anterior, más algunos bytes más que definen la longitud de la matriz y el tamaño de cada elemento (y posiblemente el número de dimensiones, la longitud de cada dimensión extra, etc.), seguidos por todos los campos de la primera elemento, luego todos los campos del segundo, etc. Dada una referencia a un objeto, el sistema puede examinar fácilmente el encabezado y determinar de qué tipo es.
Las ubicaciones de almacenamiento de tipo de referencia tienen un valor de cuatro u ocho bytes que identifica de manera única un objeto almacenado en el montón. En las implementaciones actuales, ese valor es un puntero, pero es más fácil (y semánticamente equivalente) pensarlo como un "ID de objeto".
Las ubicaciones de almacenamiento de valor mantienen el contenido de los campos del tipo de valor, pero no tienen ningún encabezado asociado. Si el código declara una variable de tipo Int32
, no es necesario que almacene información con ese Int32
diciendo de qué se trata. El hecho de que esa ubicación contenga un Int32
se almacena efectivamente como parte del programa, por lo que no tiene que almacenarse en la ubicación misma. Esto representa un gran ahorro si, por ejemplo, uno tiene un millón de objetos, cada uno de los cuales tiene un campo del tipo Int32
. Cada uno de los objetos que contienen el Int32
tiene un encabezado que identifica la clase que puede operarlo. Dado que una copia de ese código de clase puede operar en cualquiera de las millones de instancias, tener el hecho de que el campo es Int32
ser parte del código es mucho más eficiente que tener el almacenamiento para cada uno de esos campos, incluir información sobre lo que es .
El boxeo es necesario cuando se realiza una solicitud para pasar el contenido de una ubicación de almacenamiento de tipo de valor a un código que no sabe esperar ese tipo de valor particular. El código que espera objetos de tipo desconocido puede aceptar una referencia a un objeto almacenado en el montón. Como cada objeto almacenado en el montón tiene un encabezado que identifica qué tipo de objeto es, el código puede usar ese encabezado cada vez que sea necesario usar un objeto de una forma que requiera conocer su tipo.
Tenga en cuenta que en .net, es posible declarar lo que se denominan clases y métodos genéricos. Cada una de esas declaraciones genera automáticamente una familia de clases o métodos que son idénticos, excepto el tipo de objeto sobre el que esperan actuar. Si uno pasa un Int32
a una rutina DoSomething<T>(T param)
, eso generará automáticamente una versión de la rutina en la cual cada instancia del tipo T
se reemplaza efectivamente por Int32
. Esa versión de la rutina sabrá que cada ubicación de almacenamiento declarada como tipo T
contiene un Int32
, así como en el caso donde una rutina estaba codificada para usar una ubicación de almacenamiento Int32
, no será necesario almacenar información de tipo con aquellos ubicaciones mismas.
Viniendo de C++ a Java, quedé completamente completamente conmocionado cuando descubrí este hecho ... – GuLearn