This is not a question of what is boxing and unboxing, it is rather why do languages like Java and C# need that ?
I am greatly familiar wtih C++, STL and Boost.
In C++ I could write something like this very easily,
std::vector<double> dummy;
I have some experience with Java, but I was really surprised because I had to write something like this,
ArrayList<Double> dummy = new ArrayList<Double>();
My question, why should it be an Object, what is so hard technically to include primitive types when talking about Generics ?
Boxing and unboxing enables a unified view of the type system wherein a value of any type can ultimately be treated as an object. With Boxing and unboxing one can link between value-types and reference-types by allowing any value of a value-type to be converted to and from type object.
Boxing and unboxing are important concepts in C#. The C# Type System contains three data types: Value Types (int, char, etc), Reference Types (object) and Pointer Types. Basically, Boxing converts a Value Type variable into a Reference Type variable, and Unboxing achieves the vice-versa.
C# provides us with Value types and Reference Types. Value Types are stored on the stack and Reference types are stored on the heap. The conversion of value type to reference type is known as boxing and converting reference type back to the value type is known as unboxing.
When you use a generic list the compiler outputs specialized code for that value type so that the actual values are stored in the list rather than a reference to objects that contain the values. Therefore no boxing is required.
what is so hard technically to include primitive types when talking about Generics ?
In Java's case, it's because of the way generics work. In Java, generics are a compile-time trick, that prevents you from putting an Image
object into an ArrayList<String>
. However, Java's generics are implemented with type erasure: the generic type information is lost during run-time. This was for compatibility reasons, because generics were added fairly late in Java's life. This means that, run-time, an ArrayList<String>
is effectively an ArrayList<Object>
(or better: just ArrayList
that expects and returns Object
in all of its methods) that automatically casts to String
when you retrieve a value.
But since int
doesn't derive from Object
, you can't put it in an ArrayList that expects (at runtime) Object
and you can't cast an Object
to int
either. This means that the primitive int
must be wrapped into a type that does inherit from Object
, like Integer
.
C# for example, works differently. Generics in C# are also enforced at runtime and no boxing is required with a List<int>
. Boxing in C# only happens when you try to store a value type like int
in a reference type variable like object
. Since int
in C# inherits from Object
in C#, writing object obj = 2
is perfectly valid, however the int will be boxed, which is done automatically by the compiler (no Integer
reference type is exposed to the user or anything).
Boxing and unboxing are a necessity born out of the way that languages (like C# and Java) implement their memory allocation strategies.
Certain types are allocated on the stack and other on the heap. In order to treat a stack-allocated type as a heap-allocated type, boxing is required to move the stack-allocated type onto the heap. Unboxing is the reverse processes.
In C# stack-allocated types are called value types (e.g. System.Int32
and System.DateTime
) and heap-allocated types are called reference types (e.g. System.Stream
and System.String
).
In some cases it is advantageous to be able to treat a value type like a reference type (reflection is one example) but in most cases, boxing and unboxing are best avoided.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With