简体   繁体   中英

Java multidimensional array - Why is only defining the first size enough?

With the following Java examples:

int[] array1 = new int[]; // Incorrect, since no size is given
int[] array2 = new int[2]; // Correct
int[][][] array3 = new int[][][]; // Incorrect, since no size is given
int[][][] array4 = new int[2][2][2]; // Correct
int[][][] array5 = new int[2][][]; // Correct (why is this correct?)

So, my question is, why is assigning only the first size of a multidimensional array sufficient enough? I thought you always had to assign a size, even to each individual array-part of a multidimensional array, but today I found out that array5 is also a correct way for Java. Now I'm just wondering why. Can someone give some examples of why this works for multidimensional arrays and/or the reasoning behind it?

Also, I guess that the following applies as well then:

int[][][] array6 = new int[][2][]; // Incorrect
int[][][] array7 = new int[][][2]; // Incorrect
int[][][] array8 = new int[][2][2]; // Incorrect
int[][][] array9 = new int[2][2][]; // Correct
int[][][] array10 = new int[2][][2]; // Incorrect?? (Or is this correct?)

I'm a bit puzzled now and would like some clarification if someone knows it.


EDIT / SEMI-SOLUTION:

Ok, I found out why the first part works:

int[][] array = new int[2][];
array[0] = new int[5];
array[1] = new int[3];
// So now I have an array with the following options within the array-index bounds:
// [0][0]; [0][1]; [0][2]; [0][3]; [0][4]; [1][0]; [1][1]; [1][2]
// It basically means I can have different sized inner arrays

The only thing left to answer is if:

int[][][] array10 = new int[2][][2]; // Incorrect?? (Or is this correct?)

is valid or not.

to start simple: a 2-dimensional array is an array of arrays. arrays in Java are object. Only defining the first size thus creates an array of given size, which could store other arrays, but those are at this point still null. So before using it, you would need call something like array1[0] = new int[5] , or you would get a NullPointerException. for more-dimensional arrays, this applies accordingly.

Theoretically, all the "inner" arrays could have different length, actually. So you could write something like: array1[0] = new int[1]; array1[1] = new int[4]; array1[0] = new int[1]; array1[1] = new int[4]; .

about your last question: This is not valid, the Java compiler will say something like "Cannot specify an array dimension after an empty dimension". This is due to the fact that the second level was not specified, and are thus null-objects in the first-level array, and as such, no dimension can be specified on those null-arrays.

Because you aren't defining a multidimensional array. What you're actually defining is an array of arrays of arrays of int s. For example, you could do something like this:

int[][] array1 = new int[5][];
for(int i = 0; i < 5; i++){
    array1[i] = new int[i];
}

Which results in a jagged array.

So int[2][] defines a array of arrays. int[2][2] defines an array of arrays, and also defines all of the internal arrays. int[][2] attempt to define all of the internal arrays, without having anything to put them in, so it fails.

Another way to think of this is that you can later change the references stored in the outermost array (ie. change a row of values), but you can't modify along the other axis (change a column). So this is valid:

int[][] arr = new int[2][2];
arr[0] = new int[3];

while this isn't:

int[][] arr = new int[2][2];
arr[][0] = new int[3];

It's because

int[][][] array = new int[n][m][p];

is equivalent to creating n-dimensional array, then filling it with references to n instances of m-dimensional array, and then filling that arrays with references to m instances of p-dimensional arrays.

When not all dimensions are present, you have partially initialized array.

int[][][] array5 = new int[2][][]; // Correct (why is this correct)

Writing this you instanciate a array of int[][]. In the memory it's a array of references to int[][]. You don't need to know the size of the int[][] since it's only a reference and the size may be different for each one.

see the memory this way :

array5:[length a ref, length of a ref]

then you instanciate the subArray0 :

... ,subArray0[ length of a ref, length of a ref], ...

and affect the sub array to the main array

array5:[refToSubArray0, length of a ref],

but no matter the length of th sub array, you only need to save the length of a reference in memory to store you subArray since it is stored elsewhere.

int[][][] array10 = new int[2][][2]; // Correct?? (Is this correct?)

it is not correct. I beleive that when you do

new int[2][2][2]

you allocate in memory :

array[ref0,ref1], sub0[ref00,ref01], sub1[ref10,ref11], sub00[int000, int001], sub00[int000, int001], sub01[int010, int011], sub10[int100, int101], sub11[int110, int111] ...

if you skip an array size, it can't allocate memory for the third sub array because it do not knows how many sub-array will be instanciated.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM