Boxing (computer programming): Difference between revisions

Content deleted Content added
No edit summary
Alternate name
 
(126 intermediate revisions by 72 users not shown)
Line 1:
{{Short description|Programming language concept}}
{{Cleanup|date=November 2006}}
{{redirect|Object type|another use|Class (computer programming)|the universal type|any type}}
In [[computer science]], an '''object type''' (a.k.a. wrapping object) is a [[datatype]] that is used in [[object-oriented programming]] to [[wrapper pattern|wrap]] a non-object type to make it look like an [[object (computer science)|object]].
{{More citations needed|date=August 2009}}
 
In [[computer science]], '''boxing''' (a.k.a. wrapping) is the transformation of placing a primitive type within an [[Object (computer science)|object]] so that the value can be used as a [[reference type|reference]]. '''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.
Some [[object-oriented programming language]]s make a distinction between objects and non-objects, often referred to as [[primitive type]]s, for reasons such as runtime efficiency and syntax or semantic issues. For example, [[Java (programming language)|Java]] has [[primitive wrapper class]]es corresponding to each primitive type: <code>Integer</code> and <code>int</code>, <code>Character</code> and <code>char</code>, <code>Float</code> and <code>float</code>, etc. Languages like [[C++]] make little or no distinction between objects and non-objects; thus, the use of object type is of little interest.
 
==Boxing==
'''Boxing''' is to place a primitive type within an object so that the primitive can be used as an object, in a language where there is a distinction between a primitive type and an object type. For example, [[List (computing)|lists]] may have certain [[Method (computer science)|methods]] which [[arrays]] might not, but the list might also require that all of its members be objects. In this case, the added functionality of the list might be unavailable to a simple array of numbers.
 
Boxing's most prominent use is in [[Java (programming language)|Java]] where there is a distinction between [[reference type|reference]] and [[value type]]s for reasons such as runtime efficiency and syntax and semantic issues. In Java, a {{Java|LinkedList}} can only store values of type {{Java|Object}}. One might desire to have a {{Java|LinkedList}} of {{Java|int}}, but this is not directly possible. Instead Java defines [[primitive wrapper class]]es corresponding to each [[primitive data type|primitive type]]: {{Java|Integer}} and {{Java|int}}, {{Java|Character}} and {{Java|char}}, {{Java|Float}} and {{Java|float}}, etc. One can then define a {{Java|LinkedList}} using the boxed type {{Java|Integer}} and insert {{Java|int}} values into the list by boxing them as {{Java|Integer}} objects. (Using [[generic programming|generic]] parameterized types introduced in [[Java Platform, Standard Edition|J2SE]] 5.0, this type is represented as {{Java|LinkedList<Integer>}}.)
For a more concrete example, in Java, a {{Javadoc:SE|java/util|LinkedList}} can change its size, but an array must have a fixed size. One might desire to have a <code>LinkedList</code> of <code>int</code>s, but the <code>LinkedList</code> class only lists objects—it cannot list primitive types.
 
On the other hand, [[C Sharp (programming language)|C#]] has no primitive wrapper classes, but allows boxing of any value type, returning a generic {{C sharp|Object}} reference. In [[Objective-C]], any primitive value can be prefixed by a {{ObjC|@}} to make an {{ObjC|NSNumber}} out of it (e.g. {{ObjC|@123}} or {{ObjC|@(123)}}). This allows for adding them in any of the standard collections, such as an {{ObjC|NSArray}}.
To get around this, <code>int</code>s can be boxed into <code>Integer</code>s, which are objects, and then added to a <code>LinkedList</code> of <code>Integer</code>s. (Using [[generic programming|generic]] parameterized types introduced in [[J2SE]] 5.0, this type is represented as <code>LinkedList<Integer></code>.)
 
[[Haskell]] has little or no notion of [[reference type]], but still uses the term "boxed" for the runtime system's uniform pointer-to-[[tagged union]] representation.<ref>{{cite web |title=7.2. Unboxed types and primitive operations |url=https://downloads.haskell.org/~ghc/6.12.1/docs/html/users_guide/primitives.html |website=downloads.haskell.org |access-date=10 August 2022}}</ref>
===Autoboxing===
Autoboxing is the term for treating a primitive type as an object type without any extra source code. The compiler automatically supplies the extra code needed to perform the [[type conversion]].
 
The boxed object is always a copy of the value object, and is usually [[immutable object|immutable]]. Unboxing the object also returns a copy of the stored value. Repeated boxing and unboxing of objects can have a severe performance impact, because boxing [[dynamic memory allocation|dynamically allocates]] new objects and unboxing (if the boxed value is no longer used) then makes them eligible for [[garbage collection (computer science)|garbage 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.
For example, as of J2SE 5.0, Java will now allow the programmer to create a <code>LinkedList</code> of <code>int</code>s. This does not contradict what was said above: the <code>LinkedList</code> still only lists objects, and it cannot list primitive types. But now, when Java expects an object but receives a primitive type, it immediately converts that primitive type to an object. Note that the declaration List<int> is illegal in Java, but List<Integer> is not, and autoboxing will allow adding of primitive ints to the collection
 
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.
This action is called ''autoboxing'', because it is boxing that is done automatically and implicitly instead of requiring the programmer to do so manually.
 
===Unboxing=Autoboxing==
Autoboxing is the term for treatinggetting a primitivereference type asout anof objecta value type withoutjust anythrough extra[[type sourceconversion]] code(either implicit or explicit). The compiler automatically supplies the extra codesource neededcode tothat performcreates the [[type conversion]]object.
Unboxing refers to a boxed primitive type which has been broken down and the primitive type retrieved for a process of some kind such as a mathematical operation.
 
For example, in versions of Java prior to J2SE 5.0, the following code did not compile:
 
<syntaxhighlight lang=Java>
Integer i = new Integer(9);
Integer ji = new Integer(139);
Integer ki = i + j9; // error in versions prior to 5.0!
</syntaxhighlight>
 
Compilers prior to 5.0 would not accept the last line. {{Java|Integer}} are reference objects, on the surface no different from {{Java|List}}, {{Java|Object}}, and so forth. To convert from an {{Java|int}} to an {{Java|Integer}}, 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 value {{Java|9}}.<ref>[https://docs.oracle.com/javase/1.5.0/docs/guide/language/autoboxing.html oracle.com Java language guide entry on autoboxing]</ref> This means that, from J2SE 5.0 on, something like {{Java|1=Integer c = a + b}}, where {{Java|a}} and {{Java|b}} are {{Java|Integer}} themselves, will compile now — a and b are unboxed, the integer values summed up, and the result is autoboxed into a new {{Java|Integer}}, which is finally stored inside variable {{Java|c}}. 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 the {{Java|Objects.equals}} method.
As of J2SE 5.0, the <code>Integer</code>s <code>i</code> and <code>j</code> are unboxed into <code>int</code>s, the two are added, and then the sum is autoboxed into a new <code>Integer</code>. [http://java.sun.com/j2se/1.5.0/docs/guide/language/autoboxing.html] Originally, the compiler would not accept the last line. <code>Integer</code>s are objects, on the surface no different from <code>List</code>, <code>Object</code>, and so forth; mathematical operators such as <code>+</code> were not meaningfully defined for them. But the following code would of course be accepted without complaint:
 
Another example: J2SE 5.0 allows the programmer to treat a collection (such as a {{Java|LinkedList}}) as if it contained {{Java|int}} values instead of {{Java|Integer}} 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 a {{Java|LinkedList<int>}}, but it must be a {{Java|LinkedList<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 write {{Java|list.add(3)}} and think as if the {{Java|int}} {{Java|3}} were added to the list; but, the compiler will have actually transformed the line into {{Java|list.add(new Integer(3))}}.
int i = 9;
int j = 13;
int k = i + j;
 
===Automatic unboxing===
Another example:
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:
int x = 4;
int y = 5;
// Integer qBox = new Integer(x + y);
Integer qBox = x + y; // would have been an error, but okay now - equivalent to previous line
 
<syntaxhighlight lang=Java>
[[Category:Data types]]
Integer ik = new Integer(94);
[[Category:Java programming language]]
int l = k.intValue(); // always okay
Integerint qBoxm = xk; + y; // would have been an error, but okay now - equivalent to previous line
</syntaxhighlight>
 
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.
[[nl:Boxing]]
 
[[ja:ボックス化]]
In both languages, automatic boxing does not downcast automatically, i.e. the following code won't compile:
 
C#:
<syntaxhighlight lang="csharp">
int i = 942;
object o = i; // box
int j = o; // unbox (error)
Console.WriteLine(j); // unreachable line, author might have expected output "42"
</syntaxhighlight>
 
Java:
<syntaxhighlight lang="java">
int ji = 1342;
Object o = i; // box
int j = o; // unbox (error)
System.out.println(j); // unreachable line, author might have expected output "42"
</syntaxhighlight>
 
== Boxing in Rust ==
[[Rust (programming language)|Rust]] has the {{Code|Box}} type, which represents a uniquely owned, heap-allocated value:<ref>{{cite web |title=std::boxed - Rust |url=https://doc.rust-lang.org/std/boxed/index.html |website=doc.rust-lang.org |access-date=2 June 2025}}</ref>
<syntaxhighlight lang="rust">
let number: Box<i32> = Box::new(42);
</syntaxhighlight>
If the value needs to have shared ownership (e.g. between threads), one can use {{Code|Arc}}, which represents a reference-counted, heap-allocated value.<ref>{{cite web |title=Arc in std::sync - Rust |url=https://doc.rust-lang.org/std/sync/struct.Arc.html |website=doc.rust-lang.org |access-date=18 January 2025}}</ref><ref>{{cite web |title=Arc - Rust By Example |url=https://doc.rust-lang.org/rust-by-example/std/arc.html |website=doc.rust-lang.org |access-date=18 January 2025}}</ref>
 
==Type helpers==
Modern [[Object Pascal]] has yet another way to perform operations on simple types, close to boxing, called type helpers in [[FreePascal]] or record helpers in [[Delphi (programming language)|Delphi]] and [[FreePascal]] in Delphi mode.<br>
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-time [[type inference]] on strongly typed variables.<br>
But the feature is related to boxing.<br>
It allows the programmer to use constructs like
<syntaxhighlight lang="pascal">
{$ifdef fpc}{$mode delphi}{$endif}
uses sysutils; // this unit contains wraps for the simple types
var
x:integer=100;
s:string;
begin
s:= x.ToString;
writeln(s);
end.
</syntaxhighlight>
 
==References==
{{Reflist}}
 
{{Data types}}
 
[[Category:Data types]]
[[Category:Java (programming language)]]
[[Category:Programming language concepts]]