Meine Vermutung wäre, dass das mit der internen Verwaltung der Arrays zusammenhängt.
Java ist ja in vielen Dingen C-ähnlich. Dort werden Arrays als Zeiger auf die erste Speicheradresse angelegt (Die Länge wird in C nicht gespeichert, deswegen kann es da zum Überlauf kommen. Java speichert die Länge auch mit und kann deswegen eine ArrayIndexOutOfBoundsException werfen).
ist also eigentlich ein Zeiger auf eine Adresse, z.B. 0xABCD.
Mit array[0] kann man jetzt auf das erste Element zugreifen, dabei wird der Wert in den Klammern zur Startadresse addiert. Intern wird das dann zu *(0xABCD + 0x0000).
array[1] ist dann das zweite Element, das liegt dann in *(0xABCD + 0x0001).
Genau genommen stimmt das jetzt nicht ganz, weil beim Zugriff natürlich auch die Breite jedes einzelnen Elements beachtet werden muss. Bei einem 32bit int sind das 4 Byte, also liegt array[1] eigentlich an *(0xABCD+0x0004). Das erledigt der Compiler aber automatisch, darum muss man sich also meistens nicht selber kümmern.