Почему метод finalize () в java.ленг.Объект "защищен"?
из любопытства,
почему finalize()
модификатор доступа метода выполнен как protected
. Почему этого не может быть?--3-->? Может кто-нибудь объяснить мне какую-то конкретную причину этого?
кроме того, я узнал, что finalize()
метод вызывается только один раз. Если я назову это дважды в своей программе внутренне, что происходит? Сборщик мусора позвонит еще раз?
private void dummyCall() {
try {
finalize();
finalize();
} catch (Throwable e) {
e.printStackTrace();//NOT REACHES EXCEPTION
}
}
9 ответов
я отвечаю на ваш вопрос другим вопросом:
почему
finalize
метод не должен быть защищен?
в общем, вы должны стараться держать вещи как можно более конфиденциальными. Вот что такое инкапсуляция. В противном случае, вы могли бы сделать все public
. finalize
не может быть private
(поскольку производные классы должны иметь доступ к нему, чтобы иметь возможность переопределить его), поэтому он должен быть по крайней мере protected
но зачем выдавать больше доступ, когда это нежелательно?
после прочтения вашего комментария более внимательно, я думаю, что теперь я вижу вашу основную мысль. Я думаю, что ваша точка зрения, так как все происходит от java.lang.Object
и, следовательно, получает доступ к его protected
члены, это не имело бы никакого значения для него (или любого метода в java.lang.Object
если на то пошло) должны быть public
в противоположность protected
. Лично я бы посчитал это недостатком дизайна на Java. Это действительно зафиксировано в C#. Проблема не в том, почему finalize
защищен. Все нормально. Реальная проблема заключается в том, что вы не должны вызывать защищенные методы в базовом классе через ссылку на объект типа базового класса. У Эрика Липперта есть запись в блог обсуждение того, почему разрешение такого рода доступа к защищенным членам-плохая идея, которая подробнее о переполнении стека в этом вопросе.
почему доступ к методу finalize () модификатор выполнен защищенным. Почему? разве это не публично?
он не является общедоступным, потому что он не должен вызываться кем-либо, кроме JVM. Однако он должен быть защищен, чтобы его можно было переопределить подклассами, которым необходимо определить поведение для него.
Если я вызову его дважды в моей программе, что происходит внутри?
Вы можете назвать это все, что вы хотите, его просто в конце концов, метод. Однако, очень нравится public static void main(String [] args)
, Это имеет особое значение для JVM
будет ли сборщик мусора вызывать это опять?
да
- finalize предназначен для вызова только gc и как таковой не требует открытого доступа
- finalize гарантированно вызывается только один раз gc, называя его себя нарушит эту гарантию, так как gc не будет знать об этом.
- любой переопределяющий класс может сделать finalize общедоступным, что я считаю плохим по вышеуказанным причинам
- finalize не должен содержать много кода, так как любое исключение, вызванное finalize, может убить поток финализатора gc.
разглагольствовать против finalize ()
- управление собственными ресурсами или любым ресурсом, который требует вызова dispose() или close (), может вызвать трудности с поиском ошибок, поскольку они будут выпущены только тогда, когда у jvm закончится память, вы должны освободить ресурсы вручную. Завершить работу следует использовать только для отладки утечек ресурсов или для случаев, когда управление ресурсами вручную-слишком много работы.
- finalize будет вызван в дополнительный поток gc и может вызвать проблемы с блокировкой ресурсов и так далее.
- ссылочные классы, такие как WeakReference и ReferenceQueue, являются альтернативным (довольно сложным) способом очистки и могут иметь те же проблемы, что и finalize() для собственных ресурсов.
остерегайтесь ошибок в приведенных выше утверждениях, я немного устал : -)
проверить этой ссылке что обсуждает это.
в принципе, было бы разумнее всего, чтобы это было private
, поскольку он должен вызываться только JVM (сборщиком мусора). Но для того, чтобы позволить подклассу вызывать parent finalize()
метод как часть его finalize()
, должно быть protected
.
(редактировать - и просто общее предостережение-использование метода finalize () обычно не рекомендуется, поскольку нет никакого способа гарантировать, что он когда-либо будет называемый. Хотя это не означает, что у вас никогда не будет возможности использовать его - это просто редкость.)
о finalize()
вызов только один раз применяется только к вызовам из GC. Вы можете представить объект как имеющий скрытый флаг"finalize()
был вызван GC", и GC проверяет этот флаг, чтобы знать, что делать с объектом. Флаг никоим образом не влияет на ваши собственные звонки ручной работы на finalize()
.
по завершении прочтите в этой статье от Ханса Бема (который известен своей работой по сбору мусора). Это откровение о завершение; в частности, Бем объясняет, почему завершение обязательно асинхронно. Следствием этого является то, что, хотя завершение является мощным инструментом, оно очень редко является правильным инструментом для данной работы.
- Это не public
(или доступ по умолчанию), потому что он предназначен для вызова JVM внутренне, когда объект является собранным мусором - это не предназначен для вызова чем-либо еще. И это не private
потому что он должен быть переопределен, и вы не можете переопределить частные методы.
Если я вызову его дважды в моей программе, что происходит внутри? Будет сборщик мусора назовет это опять?
вероятно, да, но это трудно представить себе сценарий, в котором это имело бы какой - либо смысл-точка finalize()
выполнять очистку, когда объект является собранным мусором. И это даже не так хорошо, поэтому это действительно то, чего вы должны избегать, а не экспериментировать.
finalize () используется JVM только для очистки ресурсов при сборе объекта. Для класса разумно определить, какие действия следует предпринять для коллекции, для которой может потребоваться доступ к super.завершать.)( На самом деле для внешнего процесса нет смысла вызывать finalize(), так как внешний процесс не имеет контроля над тем, когда объект собирается.
кроме того, я узнал, что finalize() метод вызывается только один раз. Если я позову ... дважды в моей программе, внутренне что происходит?
вы, вероятно, спросите об этом под впечатлением деструкторов C++~. В java finalize () метод не делает никакой магии (например, очистка памяти). Его должен был вызвать сборщик мусора. Но не наоборот.
Я рекомендую вам прочитать корреспондентскую главу в "эффективной Java" Джошуа Блоха. Он говорит, что использование финализаторов-плохая практика и может вызвать проблемы с производительностью и другие проблемы, и есть только несколько случаев, когда они должны использоваться. Глава начинается следующими словами:--2-->
финализаторы непредсказуемы, часто опасно и вообще не нужно.
Я думаю, причина почему finalize
защищено было бы, что, возможно, оно переопределено некоторыми классами в JDK, и эти переопределенные методы вызываются JVM.