Как правильно удалить массив в Java

Мне 4 дня на Java, и из учебных пособий, которые я искал, инструкторы сосредоточили много усилий на объяснении, как выделить двумерный массив (например) следующим образом:

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

Ответ 1

объяснение

Вы не можете явно удалить что-то в Java. Это работа сборщиков мусора, чтобы сделать это. Он удалит все, что больше никому не используется. Так что либо

  1. пусть переменная выходит из области видимости или
  2. назначить null
  3. или любой другой экземпляр к нему.

Тогда на экземпляр массива (а также на его подмассивы) больше не ссылаются, и сборщик мусора в конце концов удалит его.


Рекомендации

Чтобы понять, почему переназначение внешнего массива достаточно для удаления внутренних массивов, вам необходимо понять, как на них ссылаются. Опять же, сборщик мусора может удалить все, что недоступно. Итак, давайте посмотрим на массив, такой как:

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}

Ответ 2

В какой-то момент, после того как массив выйдет из области видимости, сборщик мусора освободит память, если на него не будет других ссылок.

Если вы хотите обнулить вашу ссылку до того, как переменная выйдет из области видимости (имейте в виду, что если какой-то другой код имеет эту ссылку, она не будет собирать мусор):

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

...

// this will null the reference to the array
fooArray = null;

Ответ 3

В отличие от C, Java обеспечивает автоматическую сборку мусора, которая очищает массив для вас, когда он становится недоступным (то есть выходит из области видимости). Если вы хотите, вы можете сделать массив пустым, чтобы область памяти стала недоступной.

    Foo[][] fooArray = new Foo[2][3];
    .
    .
    .
    fooArray = null;
    System.gc();

Этот вызов gc не гарантирует, что JVM запустит сборщик мусора, но предполагает, что виртуальная машина Java затрачивает усилия на утилизацию неиспользуемых объектов, чтобы сделать доступной память, которую они занимают, для быстрого повторного использования. Когда управление возвращается из вызова метода, виртуальная машина Java сделала все возможное, чтобы освободить пространство от всех отброшенных объектов