【问题标题】:Java multidimensional array - Why is only defining the first size enough?Java 多维数组 - 为什么只定义第一个大小就足够了?
【发布时间】:2014-11-27 14:21:24
【问题描述】:

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

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


编辑/半解决方案:

好的,我知道为什么第一部分有效:

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

是否有效。

【问题讨论】:

    标签: java arrays multidimensional-array instantiation


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

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

      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];
      

      【讨论】:

        【解决方案3】:

        因为

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

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

        当并非所有维度都存在时,您已部分初始化数组。

        【讨论】:

          【解决方案4】:
          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],
          

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

          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] ...
          

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

          【讨论】:

            猜你喜欢
            • 2018-03-23
            • 2022-01-12
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-05-19
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多