I am confused how an collection is allowing to hold arrays of primitive data type, but not the primitive datatype itself.
What happens internally here?
My underlying question is how array is handled in Java as objects?
In current versions of Java, there is a significant schism between reference types (objects) and value types (primitives). (See Wikipedia.)
Most of the language is structured around the idea of everything being an object, with the primitives often getting in the way and creating various issues and edge cases. Most notably, when generics were introduced, they only added support for objects due to primitives working in such a fundamentally different way that it would add too much complexity.
(If I recall correctly, primitives were originally only added as a compromise since mid-90s computers and the original JVM implementations would have made everything unusably slow if everything - including basic numbers - had always been objects. As such, they have always been "different" - more primitive, if you will - from all the other types in Java for performance reasons.)
As such, we can have a List<String>
, since String
is an object, but not List<int>
. Instead, we have to wrap the int
in an object: List<Integer>
.
Now, modern collections are built upon generics, which don't support primitives. However, arrays are more fundamental and added long before generics. They do support primitives. Furthermore, arrays are objects, even if they contain int
values, in the same way that Integer
is an object despite containing an int
value.
Now, since arrays are objects, this means that int[]
is an object, meaning that it can be used with generics: List<int[]>
. int
is not an object, meaning that List<int>
cannot be used.
At least, this is the current state of Java. They have for many years been at work on Project Valhalla, which allows for the creation of custom value types beyond just int
, double
, and so on. As part of this project, they are trying to smooth over and bridge the gap between objects and primitives. In fact, it will reclassify primitives as just a specialized kind of object, a "value class", and the object-primitive distinction will be replaced with an identity-value distinction.
This project also includes "Universal Generics", i.e. finally tackling and solving all the issues with unifying generics and value types. As such, a few years from now, it may very well be fully possible to create a List<int>
and this whole answer will be completely outdated.
For an update on Project Valhalla, fresh this week in 2024-10, see Valhalla - Where Are We? by Brian Goetz.