The Java language has a lot of historical baggage. In Java, everything is an object – with the exception of primitive types such as
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.
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.