Подтвердить что ты не робот

Почему метод finalize() в java.lang.Object "защищен"?

Из любопытства

Почему модификатор доступа к методу finalize() создается как protected. Почему это не может быть public? Может ли кто-нибудь объяснить мне какую-то конкретную причину?

Кроме того, я узнал, что метод finalize() вызывается только один раз. Если я дважды назову его в своей программе, что происходит? Может ли сборщик мусора повторить это?

private void dummyCall() {
    try {
        finalize();
        finalize();
    } catch (Throwable e) {
        e.printStackTrace();//NOT REACHES EXCEPTION
    }
}
4b9b3361

Ответ 1

Я отвечу на ваш вопрос другим вопросом:

Почему метод finalize не должен быть защищен?

В общем, вы должны стараться держать все как можно более приватным. Это инкапсуляция. В противном случае вы можете сделать все public. finalize не может быть private (поскольку производные классы должны иметь доступ к нему, чтобы иметь возможность переопределить его), поэтому он должен быть по крайней мере protected, но зачем выдавать больше доступа, когда это нежелательно?


Прочитав свой комментарий более внимательно, я предполагаю, что теперь вижу ваш главный момент. Я думаю, что ваш смысл состоит в том, что все происходит от java.lang.Object и, следовательно, обращается к его членам protected, для него это не имеет никакого значения (или любой метод в java.lang.Object, если на то пошло), как public, в отличие от protected. Лично я считаю это ошибкой дизайна на Java. Это действительно исправлено в С#. Проблема не в том, почему finalize защищен. Это нормально. Реальная проблема заключается в том, что вы не должны иметь возможность вызывать защищенные методы в базовом классе через ссылку на объект типа базового класса. У Эрика Липперта есть запись в которой обсуждается, почему разрешение такого доступа к защищенным членам - это плохая идея, которая подробнее о переполнении стека в этом вопросе.

Ответ 2

Почему метод finalize() модификатор выполнен как защищенный. Зачем не может быть общедоступным?

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

Если я назову его дважды в своей программе, внутренне, что происходит?

Вы можете назвать все, что хотите, его просто метод в конце концов. Однако, как и t20, он имеет особое значение для JVM

Будет ли сборщик мусора снова?

Да

Ответ 3

  • finalize предназначен для вызова только gc и, как таковой, не требует открытого доступа
  • finalize гарантируется, что gc будет вызываться только один раз , и сам вызов нарушит эту гарантию, поскольку gc не знает об этом.
  • Любой класс переопределения может сделать окончательную публикацию, что, по моему мнению, плохо по вышеуказанным причинам.
  • finalize не должен содержать много кода, так как любое исключение, созданное завершением, может убить поток финализатора gc.

Повторите попытку finalize()

  • Управление собственными ресурсами или любым ресурсом, который требует вызова функции dispose() или close(), может вызвать затруднения в обнаружении ошибок, поскольку они будут выпущены только тогда, когда у jvm закончится нехватка памяти, вы должны освободить ресурсы вручную. Finalize следует использовать только для отладки утечек ресурсов или для случаев, когда управление ресурсами вручную слишком много.
  • finalize будет вызываться в дополнительном потоке gc и может вызвать проблемы с блокировкой ресурсов и т.д.
  • ссылочные классы, такие как WeakReference и ReferenceQueue, являются альтернативным (довольно сложным) способом борьбы с очисткой и могут иметь те же проблемы, что и finalize() для собственных ресурсов.

Опасайтесь ошибок в приведенных выше утверждениях, я немного устал: -)

Ответ 4

Просмотрите эту ссылку, в которой обсуждается это.

В принципе, для него было бы наиболее целесообразно быть private, поскольку его следует вызывать только JVM (сборщик мусора). Но чтобы позволить подклассу вызывать родительский метод finalize() как часть его finalize(), он должен быть protected.

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

Ответ 5

Часть о finalize(), вызываемая только один раз, применяется только к вызовам из GC. Вы можете представить, что объект имеет скрытый флаг "finalize() был вызван GC", а GC проверяет этот флаг, чтобы знать, что делать с объектом. Флаг никак не влияет на ваши собственные вызовы ручной работы на finalize().

В завершение прочитайте эту статью от Hans Boehm (который хорошо известен своей работой по сборке мусора). Это является открытием для окончательной доработки; в частности, Бем объясняет, почему финализация обязательно асинхронна. Следствием является то, что, хотя финализация является мощным инструментом, она редко является правильным инструментом для заданий.

Ответ 6

Это не public (или доступ по умолчанию), поскольку он должен был вызываться JVM внутри, когда объект собирает мусор - он не должен быть вызван ничем другим. И это не private, потому что это должно быть переопределено, и вы не можете переопределить частные методы.

Если я назову его дважды в своей программе, внутренне, что происходит? Будет ли сборщик мусора вызовет это снова?

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

Ответ 7

finalize() используется только JVM для очистки ресурсов при сборке объекта. Для класса разумно определить, какие действия следует предпринять при сборе, для чего ему может потребоваться доступ к super.finalize(). Для внешнего процесса на самом деле не имеет смысла вызывать finalize(), поскольку внешний процесс не имеет контроля над тем, когда объект собран.

Ответ 8

Кроме того, я узнал, что finalize() метод вызывается только один раз. Если я позвоню он дважды в моей программе, внутренне что происходит?

Вероятно, вы спрашиваете об этом под впечатлением от деструкторов С++ ~. В java finalize() метод не делает никакой магии (например, очистки памяти). Он должен быть вызван сборщиком мусора. Но не наоборот.

Я рекомендую вам прочитать соответствующую главу в Joshua Bloch "Эффективная Java". В нем говорится, что использование финализаторов является плохой практикой и может вызвать проблемы с производительностью и другими проблемами, и есть только несколько случаев, когда они должны использоваться. Глава начинается со следующих слов:

Финализаторы непредсказуемы, часто опасным и вообще ненужным.

Ответ 9

Я думаю, что причина, по которой защищена finalize, будет заключаться в том, что, возможно, она переопределяется некоторыми классами в JDK, а эти переопределенные методы вызывается JVM.