66

The Java language specification specifies that

In the Java programming language arrays are objects (§4.3.1), are dynamically created, and may be assigned to variables of type Object (§4.3.2). All methods of class Object may be invoked on an array.

So, considering arrays are objects — why did the Java designers make the decision not to allow inherit and override from it, for example, toString() or equals()?

The current syntax wouldn't allow creating anonymous classes with an array as the base class, but I don't think that was the reason for their decision.

Community
  • 1
  • 1
Heisenberg
  • 3,153
  • 3
  • 27
  • 55
  • Not exactly the reason but java wont support square brackets in naming. – SMA Dec 16 '14 at 12:46
  • 1
    I'd say this is probably because it might be considered same as the `primitive types` which as well can't be inherited or overwritten. – dot_Sp0T Dec 16 '14 at 12:47
  • 11
    In the JVM, arrays are handled with special bytecodes, not like objects. – Maroun Dec 16 '14 at 12:47
  • Actually, equals method exists in arrays. – Héctor Dec 16 '14 at 12:49
  • 1
    Wait a minute ... [§4.3.1](https://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.3.1) does _not_ say that. Or am I missing it? – Fildor Dec 16 '14 at 12:50
  • @bigdestroyer yes, but in some cases I would like to override and not make static utility to provide the equals() functionality – Heisenberg Dec 16 '14 at 12:50
  • it is a question more to JVM/Java Designers neither to simple developers. I guess, from Developers Perspective Arrays are not accessible like extending class, override some methods - it just belongs to primitive types form. Also, in JVM arrays are handled with special bytecodes. – ServerSideCat Dec 16 '14 at 12:51
  • 3
    it can be asked also why string can not be inherited. these objects are core objects – Adem Dec 16 '14 at 12:51
  • 1
    @Fildor https://docs.oracle.com/javase/specs/jls/se7/html/jls-10.html firs sentence – Heisenberg Dec 16 '14 at 12:51
  • @Heisenberg, That's true. But that's not what I meant. §4.3.1 sais: "An object is a class instance **or** an array" which implies (at least to my understanding) that there is a difference between class instances and arrays. – Fildor Dec 16 '14 at 12:52
  • I tried summarizing multiple chapters and articles whilst focusing on your question in case you were still unclear about something. Was a very interesting question to tackle. – Juxhin Dec 16 '14 at 21:10

4 Answers4

35

Java was a compromise between non-object languages and very slow languages of that time where everything was an object (think about Smalltalk).

Even in more recent languages, having a fast structure at the language level for arrays (and usually maps) is considered a strategic goal. Most people wouldn't like the weight of an inheritable object for arrays, and certainly nobody wanted this before JVM advances like JIT.

That's why arrays, while being objects, weren't designed as class instances ("An object is a class instance or an array"). There would be little benefit in having the ability to override a method on an array, and certainly not a great-enough one to counterbalance the need to check for the right method to apply (and in my opinion not a great-one enough to counterbalance the increased difficulty in code reading, similar to what happens when you override operators).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
  • Comments are not for extended discussion; this conversation has been [moved to chat](http://chat.stackoverflow.com/rooms/67172/discussion-on-answer-by-dystroy-why-are-arrays-objects-but-can-not-be-used-as-a). – Taryn Dec 18 '14 at 01:42
16

I came across UNDER THE HOOD - Objects and arrays which explains almost anything you need to know about how JVM handles arrays. In JVM, arrays are handled with special bytecodes, not like other objects we are familiar with.

In the JVM instruction set, all objects are instantiated and accessed with the same set of opcodes, except for arrays. In Java, arrays are full-fledged objects, and, like any other object in a Java program, are created dynamically. Array references can be used anywhere a reference to type Object is called for, and any method of Object can be invoked on an array. Yet, in the Java virtual machine, arrays are handled with special bytecodes.

As with any other object, arrays cannot be declared as local variables; only array references can. Array objects themselves always contain either an array of primitive types or an array of object references. If you declare an array of objects, you get an array of object references. The objects themselves must be explicitly created with new and assigned to the elements of the array.

Arrays are dynamically created objects, and they serve as a container that hold a (constant) number of objects of the same type. It looks like arrays are not like any other object, and that's why they are treated differently.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Maroun
  • 94,125
  • 30
  • 188
  • 241
  • 3
    Arrays don't hold objects. They hold primitive values or object *references*. Even an `int[][]` isn't an array of arrays; it's an array of *references* to arrays. If `foo` is an an array of arrays (in a language like C that supports such things) the statement `foo[0][0]++;` will not affect `foo[1][0]`, but such a thing is not guaranteed with Java's arrays of references to arrays. If `foo[0]` and `foo[1]` both identify the same instance of `int[]`, then `foo[0][0]++` will increment `foo[1][0]`. – supercat Dec 17 '14 at 16:45
8

I'd like to point out this article. It seems as though arrays and objects follow different opcodes. I can't honestly summarize it more than that however it seems, arrays are simply not treated as Objects like we're normally used to so they don't inherit Object methods.

Full credits to the author of that post as it's a very interesting read, both short & detailed.


Upon further digging into the topic via multiple sources I've decided to give a more elaborate version of my previous answer.

The first thing to note that instantiation of Objects and Arrays are very different within the JVM, their follow their respective bytecode.

Object:

Object instantiation follows a simple Opcode new which is a combination of two operands - indexbyte1 & indexbyte2. Once instantiated the JVM pushes the reference to this object onto the stack. This occurs for all objects irrespective of their types.


Arrays:

Array Opcodes (regarding instantiation of an array) however are divided into three different codes.

newarray - pops length, allocates new array of primitive types of type indicated by atype, pushes objectref of new array

newarray opcode is used when creating arrays that involve primitive datatypes (byte short char int long float double boolean) rather than object references.

anewarray - pops length, allocates a new array of objects of class indicated by indexbyte1 and indexbyte2, pushes objectref of new array

anewarray opcode is used when creating arrays of object references

multianewarray - pops dimensions number of array lengths, allocates a new multidimensional array of class indicated by indexbyte1 and indexbyte2, pushes objectref of new array

multianewarray instruction is used when allocating multi-dimensional arrays


Object can be a class instance or an array.

Take from Oracle Docs

A class instance is explicitly created by a class instance creation expression

BUT

An array is explicitly created by an array creation expression

This goes hand in hand with the information regarding the opcodes. Arrays are simply not developed to be class interfaces but are instead explicitly created by array creation expression thus naturally wouldn't implicitly be able to inherit and/or override Object.

As we have seen, it has nothing to do with the fact that arrays may hold primitive datatypes. After giving it some thought though, it isn't very common to come across situations where one might want to toString() or equals() however was still a very interesting question to try and answer.


Resources:

Oracle-Docs chapter 4.3.1

Oracle-Docs chapter 15.10.1

Artima - UnderTheHood

Juxhin
  • 5,068
  • 8
  • 29
  • 55
2

There are many classes in standard java library that you cannot subclass, arrays aren't the only example. Consider String, or StringBuffer, or any of the "primitive wrappers", like Integer, or Double. There are optimizations that JVM does based on knowing the exact structure of these objects when it deals with them (like unboxing the primitives, or manipulating array memory at byte level). If you could override anything, it would not be possible, and affect the performance of the programs very badly.

Dima
  • 39,570
  • 6
  • 44
  • 70
  • Comments are not for extended discussion; this conversation has been [moved to chat](http://chat.stackoverflow.com/rooms/67278/discussion-on-answer-by-dima-why-are-arrays-objects-but-can-not-be-used-as-a-ba). – Taryn Dec 19 '14 at 01:16