Che cosa è boxing e unboxing e quali sono i compromessi?
-
08-06-2019 - |
Domanda
Sto cercando una chiara, concisa e precisa risposta.
Idealmente, la risposta concreta, anche se link a spiegazioni di benvenuto.
Soluzione
Boxed valori sono strutture di dati che sono il minimo wrapper intorno tipi primitivi*.Boxed valori sono in genere memorizzati come puntatori a oggetti di l'heap.
Così, in scatola valori di utilizzare più memoria e prendere almeno due memoria i riferimenti per l'accesso:una volta a ottenere il puntatore del mouse, e un altro di seguire il puntatore al primitivo.Ovviamente questo non è il genere di cosa che si desidera nel vostro interiore loop.D'altra parte, boxed valori tipicamente giocare meglio con altri tipi di sistema.Dal momento che sono di prima classe e strutture di dati nella lingua, hanno atteso i metadati e la struttura che le altre strutture di dati sono.
In Java e Haskell insiemi generici non possono contenere privi di valori.Raccolte generiche .NET è in grado di tenere privi di valori senza penali.Dove Java generics sono solo utilizzati per la verifica in fase di compilazione, .NET generare classi specifiche per ogni tipo generico istanziato in fase di esecuzione.
Java e Haskell sono privi di matrici, ma sono decisamente meno conveniente rispetto alle altre collezioni.Tuttavia, quando il massimo delle prestazioni è necessario, vale la pena un po ' di disagi per evitare il sovraccarico di boxing e unboxing.
* Per questa discussione, un valore primitivo è uno che può essere memorizzato su lo stack di chiamate, anziché memorizzati come un puntatore a un valore sul mucchio.Spesso questo è solo il tipo di macchina (int, float, ecc), le strutture, e a volte statico dimensioni matrici..NET-terra chiama i tipi di valore (rispetto ai tipi di riferimento).Java gente li chiamano i tipi primitivi.Haskellions appena li chiamano unboxed.
** Sto puntando anche su Java, Haskell, e C# in questa risposta, perché questo è quello che so.Per quello che vale, Python, Ruby, Javascript e tutti hanno esclusivamente boxed valori.Questo è anche conosciuto come il "Tutto è un oggetto" approccio***.
*** Avvertimento:Un livello sufficientemente avanzato compilatore / JIT, in alcuni casi può effettivamente rilevare che un valore che è semanticamente boxed quando guardando il sorgente, può tranquillamente essere privi di valore in fase di runtime.In sostanza, grazie a una brillante lingua implementors vostre scatole sono a volte gratuito.
Altri suggerimenti
da C# 3.0 In un guscio di noce:
La boxe è l'atto di fusione di un valore tipo di un tipo di riferimento:
int x = 9;
object o = x; // boxing the int
unboxing è...inverso:
// unboxing o
object o = 9;
int x = (int)o;
Boxe & unboxing è il processo di conversione di un valore primitivo in un oggetto wrapper di classe (pugilato), o la conversione di un valore da un oggetto wrapper di classe per il valore di base (unboxing).
Per esempio, in java, potrebbe essere necessario convertire un int
valore in un Integer
(pugilato), se si desidera memorizzare in un Collection
perché primitive non possono essere memorizzati in un Collection
, solo gli oggetti.Ma quando si desidera ottenere di nuovo fuori del Collection
se si desidera ottenere il valore come int
e non è un Integer
così si sarebbe unbox di esso.
Boxing e unboxing di per sé non è male, ma è un compromesso.A seconda dell'implementazione del linguaggio, si può essere più lento e più intensivo di memoria rispetto al solo utilizzo di primitive.Tuttavia, può anche permettere di utilizzare più elevato livello di strutture di dati e di ottenere una maggiore flessibilità nel codice.
In questi giorni, è più comunemente discussi nel contesto di Java (e altre lingue) "autoboxing/autounboxing" caratteristica.Qui è un java centric spiegazione di autoboxing.
In .Net:
Spesso non è possibile fare affidamento su ciò che il tipo di variabile di una funzione consumano, quindi è necessario utilizzare una variabile oggetto che si estende da un minimo comune denominatore - in .Net questo è object
.
Tuttavia object
è una classe e memorizza il contenuto come riferimento.
List<int> notBoxed = new List<int> { 1, 2, 3 };
int i = notBoxed[1]; // this is the actual value
List<object> boxed = new List<object> { 1, 2, 3 };
int j = (int) boxed[1]; // this is an object that can be 'unboxed' to an int
Mentre entrambi questi contenere le stesse informazioni, la seconda lista è più grande e più lento.Ogni valore nella seconda lista è in realtà un riferimento a un object
che detiene il int
.
Questo è chiamato boxed perché il int
viene avvolta da object
.Quando il suo cast l' int
è unboxed - convertito torna al suo valore.
Per i tipi di valore (es.tutti structs
) questo è lento, e, potenzialmente, utilizza un sacco di spazio in più.
Per i tipi di riferimento (es.tutti classes
) questo è molto meno di un problema, così come sono memorizzati come riferimento in ogni caso.
Un ulteriore problema con un riquadro tipo di valore è che non è ovvio che hai a che fare con il dialogo, piuttosto che il valore.Quando si confrontano due structs
poi metti a confronto i valori, ma quando si mettono a confronto due classes
quindi (per impostazione predefinita) si stanno confrontando il riferimento - cioèsono queste la stessa istanza?
Questo può essere fonte di confusione quando si tratta con scatola tipi di valore:
int a = 7;
int b = 7;
if(a == b) // Evaluates to true, because a and b have the same value
object c = (object) 7;
object d = (object) 7;
if(c == d) // Evaluates to false, because c and d are different instances
È facile da risolvere:
if(c.Equals(d)) // Evaluates to true because it calls the underlying int's equals
if(((int) c) == ((int) d)) // Evaluates to true once the values are cast
Tuttavia è un'altra cosa a cui prestare attenzione quando si utilizzano boxed valori.
L' .NET FCL generico collezioni:
List<T>
Dictionary<TKey, UValue>
SortedDictionary<TKey, UValue>
Stack<T>
Queue<T>
LinkedList<T>
sono stati tutti progettati per superare i problemi di prestazioni di boxing e unboxing in precedenti implementazioni insieme.
Per ulteriori informazioni, vedere il capitolo 16, CLR via C# (2 ° Edizione).
La boxe è il processo di conversione di un tipo di valore in un tipo di riferimento.
Unboxing è la conversione di un tipo di riferimento in un tipo di valore.
EX: int i=123;
object o=i;// Boxing
int j=(int)o;// UnBoxing
Tipo di valore sono:
int, char e strutture,le enumerazioni.Tipo di riferimento sono:Classi,interfacce,array,stringhe e oggetti
Boxing e unboxing facilita i tipi di valore di essere trattati come oggetti.Boxe a dire la conversione di un valore a un'istanza di oggetto tipo di riferimento.Per esempio, Int
è una classe e int
è un tipo di dati.La conversione int
per Int
è un'esemplificazione di boxe, mentre la conversione Int
per int
è unboxing.Il concetto aiuta nella raccolta dei rifiuti, Unboxing, invece, converte il tipo di oggetto per tipo di valore.
int i=123;
object o=(object)i; //Boxing
o=123;
i=(int)o; //Unboxing.
Come per ogni cosa, autoboxing può essere problematico se non usato con attenzione.Il classico è quello di finire con un NullPointerException e non essere in grado di rintracciarlo.Anche con un debugger.Prova questo:
public class TestAutoboxNPE
{
public static void main(String[] args)
{
Integer i = null;
// .. do some other stuff and forget to initialise i
i = addOne(i); // Whoa! NPE!
}
public static int addOne(int i)
{
return i + 1;
}
}