This articleneeds additional citations forverification. Please helpimprove this article byadding citations to reliable sources. Unsourced material may be challenged and removed. Find sources: "Boxing" computer programming – news ·newspapers ·books ·scholar ·JSTOR(August 2009) (Learn how and when to remove this message) |
Incomputer science,boxing (a.k.a. wrapping) is the transformation of placing a primitive type within anobject so that the value can be used as areference.Unboxing is the reverse transformation of extracting the primitive value from its wrapper object.Autoboxing is the term for automatically applying boxing and/or unboxing transformations as needed.
Boxing's most prominent use is inJava where there is a distinction betweenreference andvalue types for reasons such as runtime efficiency and syntax and semantic issues. In Java, aLinkedList<T> must be such thatT is an instance ofObject. One might desire to have aLinkedList<int>, but this is not directly possible. Instead Java definesprimitive wrapper classes corresponding to eachprimitive type:Integer andint,Character andchar,Float andfloat, etc. Usinggeneric parameterized types introduced inJ2SE 5.0, one can then define aLinkedList<Integer> and insertint values into the list by boxing them asInteger objects.
On the other hand,C# has no primitive wrapper classes, but allows boxing of any value type, returning a genericObject reference. InObjective-C, any primitive value can be prefixed by a@ to make anNSNumber out of it (e.g.@123 or@(123)). This allows for adding them in any of the standard collections, such as anNSArray.
Haskell has little or no notion ofreference type, but still uses the term "boxed" for the runtime system's uniform pointer-to-tagged union representation.[1]
The boxed object is always a copy of the value object, and is usuallyimmutable. Unboxing the object also returns a copy of the stored value. Repeated boxing and unboxing of objects can have a severe performance impact, because boxingdynamically allocates new objects and unboxing (if the boxed value is no longer used) then makes them eligible forgarbage collection. However, modern garbage collectors such as the default Java HotSpot garbage collector can more efficiently collect short-lived objects, so if the boxed objects are short-lived, the performance impact may not be severe.
In some languages, there is a direct equivalence between an unboxed primitive type and a reference to an immutable, boxed object type. In fact, it is possible to substitute all the primitive types in a program with boxed object types. Whereas assignment from one primitive to another will copy its value, assignment from one reference to a boxed object to another will copy the reference value to refer to the same object as the first reference. However, this will not cause any problems, because the objects are immutable, so there is semantically no real difference between two references to the same object or to different objects (unless you look at physical equality). For all operations other than assignment, such as arithmetic, comparison, and logical operators, one can unbox the boxed type, perform the operation, and re-box the result as needed. Thus, it is possible to not store primitive types at all.
Autoboxing is the term for getting a reference type out of a value type just throughtype conversion (either implicit or explicit). The compiler automatically supplies the extra source code that creates the object.
For example, in versions of Java prior to J2SE 5.0, the following code did not compile:
Integeri=newInteger(9);Integeri=9;// error in versions prior to 5.0!
Compilers prior to 5.0 would not accept the last line.Integer are reference objects, on the surface no different fromList,Object, and so forth. To convert from anint to anInteger, one had to "manually" instantiate the Integer object. As of J2SE 5.0, the compiler will accept the last line, and automatically transform it so that an Integer object is created to store the value9.[2] This means that, from J2SE 5.0 on, something likeIntegerc=a+b, wherea andb areInteger themselves, will compile now — a and b are unboxed, the integer values summed up, and the result is autoboxed into a newInteger, which is finally stored inside variablec. The equality operators cannot be used this way, because the equality operators are already defined for reference types, for equality of the references; to test for equality of the value in a boxed type, one must still manually unbox them and compare the primitives, or use theObjects.equals method.
Another example: J2SE 5.0 allows the programmer to treat a collection (such as aLinkedList) as if it containedint values instead ofInteger objects. This does not contradict what was said above: the collection still only contains references to dynamic objects, and it cannot list primitive types. It cannot be aLinkedList<int>, but it must be aLinkedList<Integer> instead. However, the compiler automatically transforms the code so that the list will "silently" receive objects, while the source code only mentions primitive values. For example, the programmer can now writelist.add(3) and think as if theint3 were added to the list; but, the compiler will have actually transformed the line intolist.add(newInteger(3)).
With automatic unboxing the compiler automatically supplies the extra source code that retrieves the value out of that object, either by invoking some method on that object, or by other means.
For example, in versions of Java prior to J2SE 5.0, the following code did not compile:
Integerk=newInteger(4);intl=k.intValue();// always okayintm=k;// would have been an error, but okay now
C# doesn't support automatic unboxing in the same meaning as Java, because it doesn't have a separate set of primitive types and object types. All types that have both primitive and object version in Java, are automatically implemented by the C# compiler as either primitive (value) types or object (reference) types.
In both languages, automatic boxing does not downcast automatically, i.e. the following code won't compile:
C#:
inti=42;objecto=i;// boxintj=o;// unbox (error)Console.WriteLine(j);// unreachable line, author might have expected output "42"
Java:
inti=42;Objecto=i;// boxintj=o;// unbox (error)System.out.println(j);// unreachable line, author might have expected output "42"
Rust has theBox type, which represents a uniquely owned, heap-allocated value:[3]
letnumber:Box<i32>=Box::new(42);
std::boxed::Box in Rust is equivalent tostd::unique_ptr inC++, a kind ofsmart pointer.
usingstd::unique_ptr;unique_ptr<int>number=std::make_unique<int>(42);
If the value needs to have shared ownership (e.g. between threads), one can useArc, which represents a reference-counted, heap-allocated value.[4][5] This is similar tostd::shared_ptr in C++.
ModernObject Pascal has yet another way to perform operations on simple types, close to boxing, called type helpers inFreePascal or record helpers inDelphi andFreePascal in Delphi mode.
The dialects mentioned are Object Pascal compile-to-native languages, and so miss some of the features that C# and Java can implement. Notably run-timetype inference on strongly typed variables.
But the feature is related to boxing.
It allows the programmer to use constructs like
{$ifdef fpc}{$mode delphi}{$endif}usessysutils;// this unit contains wraps for the simple typesvarx:integer=100;s:string;begins:=x.ToString;writeln(s);end.