我使用Java已有4天的年龄,从我搜索的教程中,讲师将大量精力投入到如何解释如何分配二维数组(例如)上:
Foo[][] fooArray = new Foo[2][3];
...但是我没有找到任何说明如何删除它们的东西。
从内存的角度来看,变量fooArray
将指向堆中的一块内存,其中有2个元素。每个元素也指向堆中的另一个块,该块具有3个元素。
话虽这么说,我可以只引用第一个元素块,然后垃圾收集器完成这项工作吗?
Foo[1] = null;
和Foo[2] = null;
还是我必须使每个实例化的Foo元素为空?
Foo[1][1] = null;
Foo[1][2] = null;
Foo[1][3] = null;
...
答案 0 :(得分:16)
您不能在Java中显式删除某些内容。这样做是垃圾收集者的工作。它将删除任何人不再使用的任何内容。所以
null
然后不再引用该数组实例(及其子数组),垃圾回收器最终将其删除。
要了解为什么重新分配外部数组足以删除内部数组,您需要了解如何引用它们。同样,垃圾收集器可以删除 unreachable 的所有内容。因此,让我们看一下这样的数组:
int[][] outer = {{1, 2}, {3, 4}, {5, 6}};
我们有4个数组实例。一种是int[][]
类型,而三种是int[]
类型。另外,我们有一个变量outer
。实例引用如下:
___> {1, 2}
|
outer --> int[][] ---|---> {3, 4}
|
|___> {5, 6}
因此,通过删除outer
,再也没有人引用int[][]
。垃圾收集器现在可以将其删除。但这也会删除对内部数组的所有引用,因此垃圾收集器现在也可以删除它们。
现在假定您将通过另一个变量引用内部数组之一:
int[][] outer = {{1, 2}, {3, 4}, {5, 6}};
int[] thirdInner = outer[2];
other = null; // remove the reference
现在的情况
outer --> null
___> {1, 2}
|
int[][] ---|---> {3, 4}
|
|______> {5, 6}
|
thirdInner _______________|
因此,垃圾收集器现在将删除外部数组int[][]
,这还将删除对第一个和第二个内部数组的所有引用。但是第三个仍然被thirdInner
引用,因此在垃圾回收之后,我们有:
outer --> null
thirdInner --> {5, 6}
答案 1 :(得分:13)
在数组超出范围后的某个时刻,如果没有其他引用,则垃圾收集器将回收内存。
如果您想在变量超出范围之前使引用为空(请记住,如果其他代码具有此引用,则不会垃圾回收):
Foo[][] fooArray = new Foo[2][3];
...
// this will null the reference to the array
fooArray = null;
答案 2 :(得分:2)
与C不同,Java提供了自动垃圾收集功能,它将在无法访问(即超出范围)时为您清除数组。如果您希望将数组设置为null,以使内存位置无法访问。 / p>
Foo[][] fooArray = new Foo[2][3];
.
.
.
fooArray = null;
System.gc();
此gc调用不能确保JVM将运行垃圾回收器,但是它建议Java虚拟机将精力花在回收未使用的对象上,以使它们当前占用的内存可用于快速重用。当控件从方法调用返回时,Java虚拟机将尽最大努力从所有丢弃的对象中回收空间