Estoy buscando una respuesta clara, concisa y precisa.
Idealmente como la respuesta real, aunque los enlaces a buenas explicaciones son bienvenidos.
Estoy buscando una respuesta clara, concisa y precisa.
Idealmente como la respuesta real, aunque los enlaces a buenas explicaciones son bienvenidos.
language-but-not-type-agnostic
.static-language-agnostic
? No estoy seguro de que SO necesite la distinción; Sin embargo, podría ser una buena pregunta para el meta.Respuestas:
Los valores en recuadro son estructuras de datos que son envoltorios mínimos alrededor de los tipos primitivos *. Los valores en recuadro generalmente se almacenan como punteros a los objetos en el montón .
Por lo tanto, los valores en recuadro usan más memoria y toman como mínimo dos búsquedas de memoria para acceder: una para obtener el puntero y otra para seguir ese puntero a la primitiva. Obviamente, este no es el tipo de cosa que quieres en tus circuitos internos. Por otro lado, los valores en recuadro suelen jugar mejor con otros tipos en el sistema. Como son estructuras de datos de primera clase en el lenguaje, tienen los metadatos y la estructura esperados que tienen otras estructuras de datos.
En Java y Haskell, las colecciones genéricas no pueden contener valores sin caja. Las colecciones genéricas en .NET pueden contener valores sin caja sin penalizaciones. Cuando los genéricos de Java solo se usan para la verificación de tipos en tiempo de compilación, .NET generará clases específicas para cada tipo genérico instanciado en tiempo de ejecución .
Java y Haskell tienen matrices sin caja, pero son claramente menos convenientes que las otras colecciones. Sin embargo, cuando se necesita un rendimiento máximo, vale la pena un pequeño inconveniente para evitar la sobrecarga de boxeo y unboxing.
* Para esta discusión, un valor primitivo es cualquiera que pueda almacenarse en la pila de llamadas , en lugar de almacenarse como un puntero a un valor en el montón. Con frecuencia, son solo los tipos de máquina (ints, flotantes, etc.), estructuras y, a veces, matrices de tamaño estático. .NET-land los llama tipos de valor (a diferencia de los tipos de referencia). La gente de Java los llama tipos primitivos. Haskellions simplemente los llama sin caja.
** También me estoy centrando en Java, Haskell y C # en esta respuesta, porque eso es lo que sé. Por lo que vale, Python, Ruby y Javascript tienen valores exclusivamente encuadrados. Esto también se conoce como el enfoque "Todo es un objeto" ***.
*** Advertencia: un compilador / JIT suficientemente avanzado puede detectar en algunos casos que un valor que está semánticamente encuadrado al mirar la fuente, puede ser un valor sin caja en tiempo de ejecución. En esencia, gracias a los brillantes implementadores de lenguaje, sus cajas a veces son gratuitas.
fuente
de C # 3.0 en pocas palabras :
fuente
Boxing & unboxing es el proceso de convertir un valor primitivo en una clase de contenedor orientado a objetos (boxing), o convertir un valor de una clase de contenedor orientado a objetos al valor primitivo (unboxing).
Por ejemplo, en Java, es posible que deba convertir un
int
valor en unInteger
(boxeo) si desea almacenarlo en unCollection
porque las primitivas no se pueden almacenar en unCollection
solo objeto. Pero cuando desee recuperarlo,Collection
es posible que desee obtener el valor comoint
y no como,Integer
por lo que lo desempaquetará.El boxeo y el desempaquetado no es inherentemente malo , pero es una compensación. Dependiendo de la implementación del lenguaje, puede ser más lento e intensivo en memoria que solo usar primitivas. Sin embargo, también puede permitirle utilizar estructuras de datos de nivel superior y lograr una mayor flexibilidad en su código.
En estos días, se discute más comúnmente en el contexto de la función de "autoboxing / autounboxing" de Java (y de otros idiomas). Aquí hay una explicación centrada en Java del autoboxing .
fuente
En la red:
A menudo no puede confiar en el tipo de variable que consumirá una función, por lo que debe usar una variable de objeto que se extienda desde el mínimo común denominador, en .Net esto es
object
.Sin embargo,
object
es una clase y almacena su contenido como referencia.Si bien ambos contienen la misma información, la segunda lista es más grande y más lenta. Cada valor en la segunda lista es en realidad una referencia a un
object
que contiene elint
.Esto se llama en caja porque
int
está envuelto porobject
. Cuando se vuelve a lanzar,int
se desempaqueta: se vuelve a convertir en su valor.Para los tipos de valor (es decir, todos
structs
) esto es lento y potencialmente usa mucho más espacio.Para los tipos de referencia (es decir, todos
classes
) esto es mucho menos problemático, ya que de todos modos se almacenan como referencia.Otro problema con un tipo de valor en caja es que no es obvio que se trata de la caja, en lugar del valor. Cuando compara dos,
structs
entonces está comparando valores, pero cuando compara dos,classes
entonces (por defecto) está comparando la referencia, es decir, ¿son la misma instancia?Esto puede ser confuso cuando se trata de tipos de valores encuadrados:
Es fácil evitarlo:
Sin embargo, es otra cosa a tener en cuenta cuando se trata de valores encuadrados.
fuente
Object
no implementa el operador de igualdad, pero los tipos de clase se pueden comparar con elIs
operador; por el contrario,Int32
se puede usar con el operador de igualdad, pero noIs
. Esa distinción hace mucho más claro qué tipo de comparación se está haciendo.Boxing
es el proceso de conversión de un tipo de valor en un tipo de referencia. Mientras queUnboxing
es la conversión de un tipo de referencia en un tipo de valor.Tipos de valor son:
int
,char
ystructures
,enumerations
. Tipos de referencia son:Classes
,interfaces
,arrays
,strings
yobjects
fuente
Las colecciones genéricas de .NET FCL:
Todos fueron diseñados para superar los problemas de rendimiento del boxeo y el unboxing en implementaciones de colecciones anteriores.
Para obtener más información, consulte el capítulo 16, CLR a través de C # (2a edición) .
fuente
El boxeo y el desempaquetado facilitan que los tipos de valor sean tratados como objetos. El boxeo significa convertir un valor a una instancia del tipo de referencia de objeto. Por ejemplo,
Int
es una clase yint
es un tipo de datos. La conversiónint
aInt
es un ejemplo de boxeo, mientras que la conversiónInt
aint
es unboxing. El concepto ayuda en la recolección de basura, Unboxing, por otro lado, convierte el tipo de objeto en tipo de valor.fuente
var ii = 123; typeof ii
devuelvenumber
.var iiObj = new Number(123); typeof iiObj
vuelveobject
.typeof ii + iiObj
vuelvenumber
. Así que este es el equivalente de JavaScript del boxeo. El valor iiObj se convirtió automáticamente en un número primitivo (sin caja) para realizar la aritmética y devolver un valor sin caja.Como cualquier otra cosa, el autoboxing puede ser problemático si no se usa con cuidado. El clásico es terminar con una NullPointerException y no poder rastrearla. Incluso con un depurador. Prueba esto:
fuente
i
se inicializa prematuramente. Conviértalo en una declaración vacía (Integer i;
) para que el compilador pueda señalar que olvidó inicializarlo, o espere para declararlo hasta que sepa su valor.