The Java language has a lot of historical baggage. In Java, everything is an object – with the exception of primitive types such as int
or byte
that represent C-like value types. While these primitives are generally more efficient, they have some serious restrictions:
You can't call methods on non-objects. There is a compiler technique called “autoboxing” that transparently wraps primitives in a full object in order to allow methods to be called on them. In Java, autoboxing is performed whenever a primitive is assigned or cast to the corresponding object type, e.g. when assigned to a variable or used as a method parameter.
Type parameters for generics must be objects due to historical Java limitations. You can't have an ArrayList<byte>
but must use an ArrayList<Byte>
: The type parameters exist only during compile time for the purpose of static type checking, while they are treated as an Object
during run time. Other languages such as C++ or C# did not use this design and can parameterize over primitive types as well.
So, while byte
is the efficient representation of a byte, the Byte
wrapper class contains all the overhead necessary for methods to be called and for the value to be used as a regular object.