In der Informatik bezeichnet Boxing ( auch Wrapping genannt) die Transformation, bei der ein primitiver Datentyp in ein Objekt eingebettet wird , sodass sein Wert als Referenz verwendet werden kann . Unboxing ist die umgekehrte Transformation, bei der der primitive Wert aus dem Wrapper-Objekt extrahiert wird. Autoboxing ist die Bezeichnung für die automatische Anwendung von Boxing- und/oder Unboxing-Transformationen nach Bedarf.
Boxen
Boxing findet seine prominenteste Anwendung in Java , wo aus Gründen der Laufzeiteffizienz sowie syntaktischer und semantischer Aspekte zwischen Referenz- und Werttypen unterschieden wird . In Java muss ein Objekt eine Instanz von `T` sein . Man könnte zwar ein `T` wünschen , aber das ist nicht direkt möglich. Stattdessen definiert Java für jeden primitiven Typ eine Wrapperklasse : `T` , `T` , `T` , `T`, `T` usw. Mithilfe generischer parametrisierter Typen, die in J2SE 5.0 eingeführt wurden, kann man dann ein `T` definieren und Werte in die Liste einfügen, indem man sie als Objekte verpackt. LinkedList<T>TObjectLinkedList<int>IntegerintCharactercharFloatfloatLinkedList<Integer>intInteger
C# hingegen kennt keine Wrapper-Klassen für primitive Datentypen, erlaubt aber das Boxing beliebiger Werttypen, wobei eine generische ObjectReferenz zurückgegeben wird. In Objective-C kann jedem primitiven Wert ein Präfix vorangestellt werden, um ihn in einen Werttyp umzuwandeln (z. B. `int` @oder ` int` ). Dadurch lassen sie sich in beliebige Standard-Collections, wie z. B. eine Liste, einfügen . NSNumber@123@(123)NSArray
Haskell kennt kaum oder gar keinen Referenztyp , verwendet aber dennoch den Begriff „boxed“ für die einheitliche Zeiger-zu- getaggte Union- Darstellung des Laufzeitsystems . [ 1 ]
Das verpackte Objekt ist stets eine Kopie des Wertobjekts und in der Regel unveränderlich . Auch beim Entpacken des Objekts wird eine Kopie des gespeicherten Werts zurückgegeben. Wiederholtes Verpacken und Entpacken von Objekten kann die Performance erheblich beeinträchtigen, da beim Verpacken dynamisch neue Objekte erzeugt werden und diese beim Entpacken (sofern der verpackte Wert nicht mehr verwendet wird) für die Speicherbereinigung freigegeben werden . Moderne Speicherbereinigungsmechanismen wie der standardmäßige Java HotSpot Garbage Collector können kurzlebige Objekte jedoch effizienter bereinigen. Sind die verpackten Objekte daher nur kurzlebig, sind die Performance-Einbußen möglicherweise nicht so gravierend.
In manchen Programmiersprachen besteht eine direkte Entsprechung zwischen einem nicht-geboxten primitiven Datentyp und einer Referenz auf einen unveränderlichen, geboxten Objekttyp. Tatsächlich lassen sich alle primitiven Datentypen in einem Programm durch geboxte Objekttypen ersetzen. Während bei einer Zuweisung von einem primitiven Datentyp zu einem anderen dessen Wert kopiert wird, kopiert eine Zuweisung von einer Referenz auf ein geboxtes Objekt zu einer anderen den Referenzwert, sodass dieser auf dasselbe Objekt verweist wie die erste Referenz. Dies verursacht jedoch keine Probleme, da die Objekte unveränderlich sind und semantisch kein Unterschied zwischen zwei Referenzen auf dasselbe oder auf verschiedene Objekte besteht (abgesehen von der physischen Gleichheit). Für alle Operationen außer Zuweisungen, wie arithmetische, Vergleichs- und logische Operatoren, kann der geboxte Datentyp entpackt, die Operation ausgeführt und das Ergebnis bei Bedarf wieder geboxt werden. Somit ist es möglich, überhaupt keine primitiven Datentypen zu speichern.
Autoboxing
Autoboxing bezeichnet das Erzeugen eines Referenztyps aus einem Werttyp allein durch Typkonvertierung (implizit oder explizit). Der Compiler liefert automatisch den zusätzlichen Quellcode, der das Objekt erzeugt.
In Java-Versionen vor J2SE 5.0 ließ sich beispielsweise folgender Code nicht kompilieren:
Integer i = new Integer ( 9 ); Integer i = 9 ; // Fehler in Versionen vor 5.0!Compiler vor Version 5.0 akzeptierten die letzte Zeile nicht. `a` und `b` Integersind Referenzobjekte, die sich oberflächlich betrachtet nicht von List`int` Object, `int` usw. unterscheiden. Um von einem `a` intin ein `b` zu konvertieren Integer, musste man das `Integer`-Objekt manuell instanziieren. Ab J2SE 5.0 akzeptiert der Compiler die letzte Zeile und transformiert sie automatisch so, dass ein `Integer`-Objekt zum Speichern des Wertes erstellt wird 9. [ 2 ] Das bedeutet, dass ab J2SE 5.0 beispielsweise `a = b`, wobei `a` und ` b` selbst Referenzobjekte sind , nun kompiliert wird – `a` und `b` werden entpackt, die Integer-Werte addiert und das Ergebnis automatisch in ein neues `Integer`-Objekt verpackt , das schließlich in der Variablen `a` gespeichert wird . Die Gleichheitsoperatoren können auf diese Weise nicht verwendet werden, da sie bereits für Referenztypen definiert sind, nämlich für die Gleichheit der Referenzen. Um die Gleichheit des Wertes in einem verpackten Typ zu testen, muss man diese weiterhin manuell entpacken und die primitiven Datentypen vergleichen oder die Methode `get` verwenden. Integerc=a+babIntegerIntegercObjects.equals
Ein weiteres Beispiel: J2SE 5.0 erlaubt es Programmierern, eine Sammlung (z. B. eine Liste LinkedList) so zu behandeln, als enthielte sie intWerte anstelle von IntegerObjekten. Dies widerspricht nicht dem oben Gesagten: Die Sammlung enthält weiterhin nur Referenzen auf dynamische Objekte und kann keine primitiven Datentypen auflisten. Sie kann keine Liste sein , muss aber eine Liste sein. Der Compiler transformiert den Code jedoch automatisch so, dass die Liste „stillschweigend“ Objekte aufnimmt, während der Quellcode nur primitive Werte erwähnt. Beispielsweise kann der Programmierer nun so schreiben und denken, als würden die Elemente der Liste hinzugefügt; der Compiler hat die Zeile jedoch tatsächlich in eine solche umgewandelt . LinkedList<int>LinkedList<Integer>list.add(3)int3list.add(newInteger(3))
Automatisches Auspacken
Bei der automatischen Entpackung liefert der Compiler automatisch den zusätzlichen Quellcode, der den Wert aus diesem Objekt abruft, entweder durch Aufruf einer Methode dieses Objekts oder auf andere Weise.
In Java-Versionen vor J2SE 5.0 ließ sich beispielsweise folgender Code nicht kompilieren:
Integer k = new Integer ( 4 ); int l = k.intValue ( ); // immer in Ordnung int m = k ; // wäre ein Fehler gewesen, aber jetzt in OrdnungC# unterstützt kein automatisches Unboxing im selben Sinne wie Java, da es keine separate Gruppe von primitiven Datentypen und Objekttypen kennt. Alle Typen, die in Java sowohl als primitive als auch als Objekttypen existieren, werden vom C#-Compiler automatisch entweder als primitive (Wert-)Typen oder als Objekttypen (Referenztypen) implementiert.
In beiden Sprachen findet kein automatisches Boxing und Downcasting statt, d. h. der folgende Code lässt sich nicht kompilieren:
C#:
int i = 42 ; object o = i ; // Box int j = o ; // Unbox (Fehler) Console.WriteLine ( j ) ; // Nicht erreichbare Zeile, Autor erwartete möglicherweise die Ausgabe "42"Java:
int i = 42 ; Object o = i ; // Box int j = o ; // Unbox (Fehler) System.out.println ( j ) ; // Nicht erreichbare Zeile, der Autor erwartete möglicherweise die Ausgabe "42 "Boxen in Rost
Rust verfügt über den BoxTyp, der einen eindeutig zugeordneten, im Heap gespeicherten Wert repräsentiert: [ 3 ]
let number : Box < i32 > = Box :: new ( 42 );std::boxed::BoxIn Rust entspricht dies dem std::unique_ptrin C++ , einer Art Smartpointer .
using std :: unique_ptr ;unique_ptr <int> number = std :: make_unique <int> ( 42 ) ;Wenn der Wert gemeinsam genutzt werden muss (z. B. zwischen Threads), kann man `std::ref` verwenden Arc, das einen referenzgezählten, im Heap allokierten Wert darstellt. [ 4 ] [ 5 ] Dies ist vergleichbar mit `std::ref` std::shared_ptrin C++.
Typhilfsfunktionen
Modernes Object Pascal bietet eine weitere Möglichkeit, Operationen auf einfachen Datentypen durchzuführen, ähnlich dem Boxing. Diese werden in Free Pascal als Typhilfsfunktionen und in Delphi sowie im Delphi -Modus als Datensatzhilfsfunktionen bezeichnet. Die genannten Dialekte sind Object-Pascal-Sprachen, die zu nativem Code kompiliert werden und daher einige Funktionen von C# und Java nicht bieten. Insbesondere fehlt die Laufzeit- Typinferenz für stark typisierte Variablen. Diese Funktion ist jedoch mit dem Boxing verwandt und ermöglicht es dem Programmierer, Konstrukte wie … zu verwenden .
{$ifdef fpc}{$mode delphi}{$endif} uses sysutils ; // diese Einheit enthält Wrapper für die einfachen Typen var x : integer = 100 ; s : string ; begin s := x . ToString ; writeln ( s ) ; end .Referenzen
- ^ „7.2. Unboxed types and primitive operations“ . downloads.haskell.org . Abgerufen am 10. August 2022 .
- ^ Eintrag zum Thema Autoboxing im Java-Sprachleitfaden von oracle.com
- ^ "std::boxed - Rust" . doc.rust-lang.org . Abgerufen am 2. Juni 2025 .
- ^ „Arc in std::sync - Rust“ . doc.rust-lang.org . Abgerufen am 18. Januar 2025 .
- ^ „Arc - Rust By Example“ . doc.rust-lang.org . Abgerufen am 18. Januar 2025 .