如何在Java中正确删除数组

Chr*_*nus 13 java arrays

我使用Java时只有4天的年龄,根据我搜索的教程,讲师将大量精力集中在解释如何分配二维数组(例如)上:

Foo[][] fooArray = new Foo[2][3];
Run Code Online (Sandbox Code Playgroud)

...但是我没有找到任何说明如何删除它们的内容。

从内存的fooArray角度来看,该变量将指向堆中的一个内存块,其中有2个元素。每个元素也指向堆中的另一个块,该块具有3个元素。

话虽这么说,我可以只引用第一个元素块,然后垃圾收集器完成这项工作吗?

Foo[1] = null;Foo[2] = null;

还是我必须使每个实例化的Foo元素都为空?

Foo[1][1] = null; Foo[1][2] = null; Foo[1][3] = null; ...

Zab*_*uza 17

说明

您不能在Java中显式删除某些内容。这样做是垃圾收集者的工作。它将删除任何人不再使用的任何内容。所以要么

  1. 让变量超出范围或
  2. 分配 null
  3. 或其他任何实例。

然后不再引用数组实例(及其子数组)并且垃圾收集器最终将其删除。


参考文献

要了解为什么重新分配外部数组足以删除内部数组,您需要了解如何引用它们。同样,垃圾收集器可以删除任何无法访问的内容。因此,让我们看一下如下数组:

int[][] outer = {{1, 2}, {3, 4}, {5, 6}};
Run Code Online (Sandbox Code Playgroud)

我们有4个数组实例。一类是类型int[][],三类是类型int[]。另外,我们有一个变量outer。实例引用如下:

                       ___> {1, 2}
                      |
outer  --> int[][] ---|---> {3, 4}
                      |
                      |___> {5, 6}
Run Code Online (Sandbox Code Playgroud)

因此,通过删除outer,没有人int[][]再引用。垃圾收集器现在可以将其删除。但这也会删除对内部数组的所有引用,因此垃圾收集器现在也可以删除它们。

现在假设您将通过另一个变量引用内部数组之一:

int[][] outer = {{1, 2}, {3, 4}, {5, 6}};
int[] thirdInner = outer[2];
other = null; // remove the reference
Run Code Online (Sandbox Code Playgroud)

现在的情况

outer  --> null

                       ___> {1, 2}
                      |
           int[][] ---|---> {3, 4}
                      |
                      |______> {5, 6}
                          |
thirdInner _______________|
Run Code Online (Sandbox Code Playgroud)

因此,垃圾收集器现在将删除外部数组int[][],这还将删除对第一个和第二个内部数组的所有引用。但是第三个仍然被引用thirdInner,因此在垃圾回收之后,我们有:

outer       --> null
thirdInner  --> {5, 6}
Run Code Online (Sandbox Code Playgroud)

  • “未引用”是棘手的-因为在某些时候所有内容都“未引用”。正确的语言是“ GC根目录的硬引用无法访问”。 (3认同)
  • “未引用”并非严格正确。“未引用”表示不会删除两个互相引用的对象或一个互相引用的对象,这显然是不正确的。垃圾收集器不会删除“未引用”的对象,而是会从GC根目录(运行线程)中删除“不可访问”的对象。当将“ null”分配给“ outer”时,整个数组和所有内部数组都无法被程序“访问”,并且全部被一次性清除。不必先删除外部数组,以发现内部数组也是可删除的。 (2认同)
  • 该短语在第一部分的介绍中很好,但是我在第二部分中对该句子进行了编辑,因为当术语与其他文献中的内容相匹配时(如果他们对更多详细信息感兴趣),它对读者很有帮助。我还添加了指向规范的链接。而且我认为说“可以”而不是“将要”很重要,因为垃圾收集是有意地不确定的。实际上,甚至“删除”一词都不符合实际情况,但我认为,最好还是这样,因为在那里有足够的进一步阅读方法。 (2认同)

Jas*_*son 13

在数组超出范围后的某个时刻,如果没有其他引用,则垃圾收集器将回收该内存。

如果要在变量超出范围之前使引用为空(请注意,如果其他代码具有此引用,则不会收集垃圾):

Foo[][] fooArray = new Foo[2][3];

...

// this will null the reference to the array
fooArray = null;
Run Code Online (Sandbox Code Playgroud)

  • 您的措词(“一次”)听起来好像*一旦*最后一个引用超出范围,将立即收回内存。这不是Java GC的一个相当重要的属性。 (3认同)