tl;dr
It's mostly for historical reasons.
Arrays are (and were) treated like a special data type from the very beginning, having e.g. distinct VM opcodes that were intended to deal only with them (note there are literally tons of opcodes for array handling!). It was mostly made that way so that the performance of the arrays would be near-native (and so that JNI could interact with them easily). The design choice here was that the need for fast/memory-efficient primitive/array data types was put before the need for a "beautiful" interface, and that thus neither primitives nor arrays can't be "real" objects for the sake of VM performance.
While the Oak Language Specification (Oak being the direct Java ancestor) stating Although arrays can be created with new, just as instances of classes are created, arrays are not currently objects.
is ancient (ca. 20 years old), it still shows the general idea of this performance-elegance tradeoff - the very idea that is reiterated with respect to contemporary Java about 15 years later in the Oracle's own Arrays 2.0 talk, giving a nice insight as to why it is the way it is, and what can we expect of it in the nearest future. I'll highlight my five cents about that very why.
First and foremost, sometimes an array is much better as a "fake" object instead of a "real" one, e.g. there are some cases (local array with <= 64 elements) when arrays are simply inlined into method code (as with local variables). Making them a regular class would make those optimizations much harder. The downside, however, is that it precluded the "regular" class/object use - since having a "regular" class/object behaviour would require the runtime to handle all the things like e.g. virtual dispatch, object constructors, GC with composition graphs etc., incurring a runtime penalty (see the footnote for a commentary). Note that String
doesn't have these issues, because it is, under the hood... just a syntactic-sugar-covered char[]
wrapper class!
Also, note that you can't e.g. just "sort" an array - there are many sort algorithms that could've been used, so the array class should've been open (overloadable etc.), if those utilities were added at all. Even more - proper design of such an interface would be (and is, as seen in C#) very tricky (due to e.g. multidimensinal arrays, nullable vs non-null arrays, possible cyclic references etc.), which would probably complicate the matter even more. OTOH, changing it would probably break backwards compatibility - so the Java devs decided it's better to let it be the way it is. Not long ago we had a bug with Java lib's own TimSort some time ago - if it were included in a final
array class, it would actually prevent the programmer from fixing it in place by overriding the method!
There are, however, both the utility class java.util.Arrays
(with all the common array utilities you may need) and thin wrapper classes allowing proper object-oriented access to arrays (e.g. ArrayList
). You can even write one yourself, and give your ArrayWrapper
anything your soul desires; being a programmer is sometimes more about creating tools than about using them.
Note: it is possible to achieve real-object-like behaviour on arrays by using e.g. a syntax-aware source preprocessor/lexer (in a way similar to how Lombok works) or by patching the compiler, which would, in turn, rewrite the pseudo-calls on arrays to a valid static method, passing the array as parameter; e.g. given a definition similar to @ArrayEx(Arrays.class) int[] array;
it would convert commands like array.sort();
into Arrays.sort(array);
- yet, paraphrasing Eric Lippert, it's not there because nobody bothered to code it. If you find yourself in dire need of it for whatever reason - just write the code and submit the patch to OpenJDK or even just publish it on GitHub... that's mostly how OSS works chuckle. Project Valhalla brings some hope here, because it's at least tangentially related to this matter - you may say that having object-like primitive values is a good way to pave a road to real object-like arrays. The aforementioned Arrays 2.0 talk actually highlights current "fake" object behaviour as one of the downsides of current implementation, mentioning some of the things I stated above as either conscious dev choices, or possible opportunities and pitfalls. All in all, maybe those good folks at Oracle/OpenJDK actually will add them in some future Java extension, who knows...