2

Why in Java programming language array is not made like a regular class, e.g. it can't be inherited from and it doesn't have any utility methods directly in its class (e.g. like a String)?

There are many methods that can be designed for arrays, e.g. swap(), searching methods, sorting methods, split/splice methods etc.

Noah Levy
  • 69
  • 1
  • 7
  • 6
    [Arrays are objects (§4.3.1), are dynamically created, and may be assigned to variables of type Object (§4.3.2)](https://docs.oracle.com/javase/specs/jls/se8/html/jls-10.html) – Andy Turner May 07 '16 at 11:28
  • Those methods could also be written for a `Collection`. – bcsb1001 May 07 '16 at 11:30
  • 3
    @NoahLevy Then please [edit] your question and rephrase it to avoid confusion. – Pshemo May 07 '16 at 11:33
  • 1
    Anyway arrays can have different dimensions. How would you like `swap(1,2)` method work for two dimensional array `int[][]`? Should such array even have such `swap` method? Should it swap rows or elements? – Pshemo May 07 '16 at 11:35
  • @Pshemo each array dimension should have its own methods, if int[] has sortMin then int[][] should have sortMinTopToBot or something like that, and all the searching methods are different for each dimension – Noah Levy May 07 '16 at 11:43
  • Now the Question is opinion-based. And moot. Java is the way it is because those were the language design choices made 20+ years ago. We don't know real reasons why they were made. Though, once you start on the slippery slop of adding "useful" methods to an `array` class, it is hard to know when to stop. – Stephen C May 07 '16 at 11:46
  • @Pshemo honestly, it *could* have been done (e.g. C# handles it by variadic methods AFAIR); the point is - *would the pros outweigh the cons?* –  May 07 '16 at 11:46
  • Erm ... why? Surely, you only get performance issues if the methods are non-final. Actually, maybe "complexity" is a plausible explanation. Complexity for people learning / using the language AND implementing it. – Stephen C May 07 '16 at 11:49
  • I think we should reopen this question so that you can give a proper explanation. I know that arrays have distinct opcodes, etc. But why does that stop the standard method invocation opcodes from being applicable to arrays-with-methods? I can see a problem with fields ... but maybe the solution would be to ban array subclasses from defining instance fields. – Stephen C May 07 '16 at 12:00
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/111288/discussion-between-vaxquis-and-stephen-c). –  May 07 '16 at 12:11

1 Answers1

6

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...

Community
  • 1
  • 1