Явное обнуление

В каких ситуациях в java явно указывается значение null. Помогает ли это сборщику мусора, делая объекты недоступными или чем-то еще? Считается ли это хорошей практикой?

Ответ 1

В Java это может помочь, если у вас очень длинный метод, и единственная ссылка на объект - через локальную переменную. Установка этой локальной переменной в нуль, когда она вам больше не нужна (но когда метод будет продолжать работать в течение длительного времени) может помочь GC. (В С# это очень редко полезно, поскольку GC учитывает "последнее возможное использование". Эта оптимизация может превратиться в Java некоторое время - я не знаю.)

Аналогично, если у вас есть поле участника, ссылающееся на объект, и вы больше не нуждаетесь в нем, вы можете потенциально помочь GC, установив поле в null.

В моем опыте, однако, очень редко бывает полезно делать любую из этих вещей, и это делает код более грязным. Очень немногие методы действительно выполняются в течение длительного времени, и установка переменной в значение null действительно не имеет ничего общего с тем, что вы хотите достичь. Это не очень хорошая практика, когда вам это не нужно, и если вам нужно, вы должны убедиться, что рефакторинг может улучшить ваш дизайн в первую очередь. (Возможно, ваш метод или тип делают слишком много.)

Обратите внимание, что установка переменной в значение null является полностью пассивной - она ​​не сообщает сборщику мусора, что объект может быть собран, он просто избегает сборщика мусора, видя, что эта ссылка служит причиной для сохранения объекта в следующий раз ( GC).

Ответ 2

В общем случае он не нужен (конечно, это может зависеть от реализации VM). Однако, если у вас есть что-то вроде этого:

private static final Map<String, String> foo;

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

Но сделаем что-то вроде этого:

void foo()
{
    Object o;

    // use o

    o = null; // don't bother doing this, it isn't going to help
}

Изменить (забыл упомянуть об этом):

Если вы работаете над этим, вы должны обнаружить, что 90-95% переменных, которые вы объявляете, можно сделать окончательными. Конечная переменная не может изменить то, на что она указывает (или ее значение для примитивов). В большинстве случаев, когда переменная является окончательной, было бы ошибкой (ошибкой), чтобы она получала другое значение во время выполнения метода.

Если вы хотите, чтобы переменная была равна нулю после использования, она не может быть окончательной, а это означает, что у вас больше шансов создать ошибки в коде.

Ответ 3

В одном специальном случае я считаю полезным, когда у вас очень большой объект и вы хотите заменить его другим большим объектом. Например, посмотрите на следующий код:

BigObject bigObject = new BigObject();
// ...
bigObject = new BigObject(); // line 3

Если экземпляр BigObject настолько велик, что вы можете иметь только один такой экземпляр в куче, строка 3 завершится с OutOfMemoryError, потому что 1-й экземпляр не может быть освобожден до тех пор, пока команда назначения в строке 3 не завершится, что очевидно после второй экземпляр готов.

Теперь, если вы установите bigObject на нуль прямо перед строкой 3:

bigObject = null;
bigObject = new BigObject(); // line 3

1-й экземпляр может быть освобожден, когда JVM заканчивается из кучи во время построения второго экземпляра.

Ответ 4

Из "Эффективной Java": используйте его для устранения устаревших ссылок на объекты. В противном случае это может привести к утечкам памяти, которые могут быть очень трудными для отладки.

public Object pop(){
    if(size == 0)
        throw new EmptyStatckException();
    Object result = elements[--size];
    elements[size] = null; //Eliminate Object reference
    return result;
}

Ответ 5

Если вы обнуляете объект, который собирается выйти из области видимости, когда ваш блок метода закрывается, тогда нет никакой пользы в плане сбора мусора. Это не редкость встретить людей, которые не понимают этого, которые работают очень трудно установить много вещей, чтобы обнулить без необходимости.

Ответ 7

Явное обнуление может помочь с GC в некоторых редких ситуациях, где все следующее верно:

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

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

Одна из ситуаций, когда явное обнуление действительно полезно: если для указания конкретного состояния используется значение null, то иногда необходимо установить и использовать значение null. Нуль полезная ценность сама по себе по нескольким причинам:

  • Нулевые проверки выполняются очень быстро, поэтому условный код, который проверяет значение null, обычно более эффективен, чем многие альтернативы (например, вызов object.equals())
  • Вы получаете немедленное исключение NullPointerException, если пытаетесь разыменовать его. Это полезно, потому что хорошо Fail Fast стиль кодирования, который поможет вам ловить логические ошибки.