简体   繁体   English

Java多维数组-为什么仅定义第一个大小就足够了?

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

With the following Java examples: 带有以下Java示例:

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. 我以为您总是必须为多维数组的每个单独的数组部分分配大小,但是今天我发现array5也是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. Java中的数组是对象。 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. 因此,在使用它之前,您需要调用array1[0] = new int[5] ,否则会得到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]; 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". 关于您的最后一个问题:这是无效的,Java编译器会说类似“在空维之后不能指定数组维”的内容。 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. 您实际上定义的是int数组的数组。 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][]定义了一个数组数组。 int[2][2] defines an array of arrays, and also defines all of the internal arrays. int[2][2]定义了一个数组数组,并且还定义了所有内部数组。 int[][2] attempt to define all of the internal arrays, without having anything to put them in, so it fails. int[][2]试图定义所有内部数组,而没有放入它们的任何内容,因此失败。

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. 等效于创建n维数组,然后用 m维数组的n个实例的引用填充它,然后用 m维数组的m个实例的引用填充该数组。

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[][]. 编写此代码可以实例化一个int [] []数组。 In the memory it's a array of references to int[][]. 在内存中,它是对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. 您不需要知道int [] []的大小,因为它只是一个参考,并且每个大小可能都不同。

see the memory this way : 以这种方式查看内存:

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

then you instanciate the subArray0 : 然后实例化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. 如果跳过数组大小,则它无法为第三个子数组分配内存,因为它不知道将实例化多少个子数组。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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