Java多维数组 - 为什么只定义第一个足够的大小?

时间:2014-10-02 14:49:03

标签: java arrays multidimensional-array instantiation

使用以下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?)

所以,我的问题是,为什么只分配多维数组的第一个大小就足够了?我以为你总是要分配一个大小,甚至是每个单独的数组 - 多维数组的一部分,但今天我发现array5也是Java的正确方法。现在我只是想知道为什么。有人可以提供一些例子,说明为什么这适用于多维数组和/或它背后的推理?

另外,我猜以下情况适用:

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?)

我现在有点困惑,如果有人知道的话,我想澄清一下。


EDIT / SEMI-SOLUTION:

好的,我发现了为什么第一部分有效:

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

唯一要回答的是:

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

是否有效。

4 个答案:

答案 0 :(得分:3)

开始简单:二维数组是一个数组数组。 Java中的数组是对象。只定义第一个大小因此会创建一个给定大小的数组,它可以存储其他数组,但此时仍为空。所以在使用它之前,你需要调用类似array1[0] = new int[5]的东西,否则你会得到一个NullPointerException。 对于更多维数组,这相应适用。

理论上,所有"内部"实际上,数组可以有不同的长度。所以你可以这样写:array1[0] = new int[1]; array1[1] = new int[4];

关于你的上一个问题: 这是无效的,Java编译器会说类似"无法在空维度后指定数组维度"。这是因为未指定第二级,因此在第一级数组中是空对象,因此,不能在这些空数组上指定维度。

答案 1 :(得分:1)

因为您没有定义多维数组。你实际定义的是int s的数组数组。例如,你可以这样做:

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

导致锯齿状阵列。

所以int[2][]定义了一个数组数组。 int[2][2]定义了一个数组数组,并定义了所有内部数组。 int[][2]尝试定义所有内部数组,而无需将它们放入,因此失败。

另一种想到这一点的方法是,您可以稍后更改存储在最外层数组中的引用(即更改一行值),但不能沿另一个轴修改(更改列)。所以这是有效的:

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

虽然不是这样:

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

答案 2 :(得分:0)

这是因为

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

相当于创建n维数组,然后用引用填充到m维数组的n个实例,然后用对p维数组的m个实例的引用填充该数组。 / p>

当并非所有尺寸都存在时,您已经部分初始化了数组。

答案 3 :(得分:0)

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

写这个你实例化一个int [] []数组。在内存中,它是对int [] []的引用数组。您不需要知道int [] []的大小,因为它只是一个参考,每个参数的大小可能不同。

以这种方式看待记忆:

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

然后你实现了subArray0:

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

并将子数组影响到主数组

array5:[refToSubArray0, length of a ref],

但无论子数组的长度如何,您只需要在内存中保存引用的长度以存储subArray,因为它存储在其他地方。

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

不正确。我相信你做的时候

new int[2][2][2]

你在内存中分配:

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

如果跳过数组大小,它就不能为第三个子数组分配内存,因为它不知道将实例化多少个子数组。