How Is Length Implemented in Java Arrays

How is length implemented in Java Arrays?

According to the Java Language Specification (specifically §10.7 Array Members) it is a field:

  • The public final field length, which contains the number of components of the array (length may be positive or zero).

Internally the value is probably stored somewhere in the object header, but that is an implementation detail and depends on the concrete JVM implementation.

The HotSpot VM (the one in the popular Oracle (formerly Sun) JRE/JDK) stores the size in the object-header:

[...] arrays have a third header field, for the array size.

Why do arrays in Java need to have a pre-defined length when Objects don't?

My question is why does a pointer to an array need to know how big the array is beforehand, when a pointer to any other object doesn't?

It doesn't. Here, this runs perfectly fine:

String[] x = new String[10];
x = new String[15];

The whole 'needs to know in advance how large it is' refers only to the ARRAY OBJECT. As in, new int[10] goes to the heap, which is like a giant beach, and creates a new treasure chest out of thin air, big enough to hold exactly 10 ints (Which, being primitives, are like coins in this example). It then buries it in the sand, lost forever. Hence why new int[10]; all by its lonesome is quite useless.

When you write int[] arr = new int[10];, you still do that, but you now also make a treasure map. X marks the spot. 'arr' is this map. It is NOT AN INT ARRAY. It is a map to an int array. In java, both [] and . are 'follow the map, dig down, and open er up'.

arr[5] = 10; means: Follow your arr map, dig down, open up the chest you find there, and you'll see it has room for precisely 10 little pouches, each pouch large enough to hold one coin. Take the 6th pouch. Remove whatever was there, put a 10ct coin in.

It's not the map that needs to know how large the chest is that the map leads to. It's the chest itself. And this is true for objects as well, it is not possible in java to make a treasure chest that can arbitrarily resize itself.

So how does ArrayList work?

Maps-in-boxes.

ArrayList has, internally, a field of type Object[]. That field doesn't hold an object array. It can't. It holds a map to an object array: It's a reference.

So, what happens when you make a new arraylist? It is a treasure chest, fixed size, with room for exactly 2 things:

  1. A map to an 'object array' treasure chest (which it will also make, with room for 10 maps, and buries it in the sand, and stores the map to this chest-of-maps inside itself.
  2. A coinpouch. The coin inside represents how many objects the list actually contains. The map to the treasure it has leads to a treasure with room for 10 maps, but this coin (value: 0) says that so far, none of those maps go anywhere.

If you then run list.add("foo"), what that does is complicated:

  1. "foo" is an object (i.e. treasure), so "foo" as an expression resolves to be a map to "foo". It then takes your list treasuremap, follows it, digs down, opens the box, and you yell 'oi! ADD THIS!', handing it a copy of your treasuremap to the "foo" treasure. What the box then does with this is opaque to you - that's the point of OO.
  2. But let's dig into the sources of arraylist: What it will do, is query its treasuremap to the object array (which is private, you can't get to it, it's in a hidden compartment that only the djinn that lives in the treasure chest can open), follows it, digs down, and goes to the first slot (why? Because the 'size coin' in the coinpouch is currently at 0). It takes the map-to-nowhere that is there, tosses it out, makes a copy of your map to the "foo" treasure, and puts the copy in there. It then replaces its coin in the coin pouch with a penny, to indicate it is now size 1.
  3. If you add an 11th element, the ArrayList djinn goes out to the other treasure, notices there is no room, and goes: Well, dang. Okay. It then conjures up an entirely new treasure chest that can hold 15 treasure maps, it copies over the 10 maps in the old treasure, moves them to the new treasurechest, adds the copy of the map of the thing you added as 11th, then goes back to its own chest, rips out the map to the real treasure and replaces it to a map of the newly made treasure (With 15 slots), and puts an 11ct coin in the pouch.
  4. The old treasure chest remains exactly where it is. If nobody has any maps to this (and nobody does), eventually, the beachcomber finds it, gets rid of it (that'd be the garbage collector).

Thus, ALL treasure chests are fixed size, but by replacing maps with new maps and conjuring up new treasure chests, you can nevertheless make it look like ArrayList is capable of shrinking and growing.

So why don't arrays allow it? Because that shrinking and growing stuff is complicated and arrays expose low-level functionality. Don't use arrays, use Lists.

Where is array's length property defined?

Arrays are special objects in java, they have a simple attribute named length which is final.

There is no "class definition" of an array (you can't find it in any .class file), they're a part of the language itself.

10.7. Array Members


The members of an array type are all of the following:

  • The public final field length, which contains the number of components of the array. length may be positive or zero.
  • The public method clone, which overrides the method of the same name in class Object and throws no checked exceptions. The return type of the clone method of an array type T[] is T[].

    A clone of a multidimensional array is shallow, which is to say that it creates only a single new array. Subarrays are shared.

  • All the members inherited from class Object; the only method of Object that is not inherited is its clone method.

Resources:

  • JLS - Arrays

length in arrays and length() in String

Simply: that's just the way it is, and the way it's always been.

It's specified in JLS section 10.7 that arrays have a public final length field. It could have been specified as a method instead, for consistency - but it just wasn't... equally String could have made an implementation decision to have a public final length field - but again, it happens not to be that way.

There are a few bits of inconsistency which have survived since 1.0 - obviously these things really can't be changed after release...

Is there a way to specify the length of an array when defining a function's return type?

Short answer is: no. You cannot do this with an array.

Longer answer is: if you find yourself in a situation that you need something like this, what your really need is a class with two fields. Based on the domain of your application it can be named differently, say for a graphics app you can have a Point class with x and y coordinates.

public class Point {
private final int x;
private final int y;

// the usual constructor, getters, setters and stuff
}

Or, if you don't want to create your own class for such a purpose you can use a tuple, like e.g. Pair from Apache Commons lib.

Classes are the way to provide such abstractions, describing the data structure you need with classes not only helps you get the job done, but makes the code more understandable for readers of your code including future you :-)

Length in Arrays

I've an assumption but I cant say that this is the reason why the designers of java did it that way.

An array is a container (and an Object of course) with a fixed length. And its a very basic one, so encapsulation in this case would be nice but not critical. Take a look at ArrayList for example, which can be considered as an encapsulation of an array.

A basic array has many benefits over other types that encapsulates it. And so maybe when the first version of Java came out it lacked most of the optimization that it has today. So having a data structure with the simplicity (in term of performance) of an array is a good thing.

Also it could be as simple as they didnt think about that at that time and afterwards they had to maintain a backwards compatibility :)

Anyway, if you find interesting stuff about that (maybe you could email sun/oracle) please post!
Thats a nice question.

Length of an object array

Arrays in Java are not resizable. Once an array is instantiated, its length cannot change. That's why the length attribute (myArray.length) can always be trusted to contain the array's length.



Related Topics



Leave a reply



Submit