Из любопытства,
Почему finalize()
модификатор доступа метода сделан как protected
. Почему наклон это быть public
? Кто-то может объяснить меня какая-либо определенная причина позади этого?
Кроме того, я узнал это finalize()
метод называют только однажды. Если я называю его дважды в моей программе внутренне, что происходит? Сборщик "мусора" назовет это снова?
private void dummyCall() {
try {
finalize();
finalize();
} catch (Throwable e) {
e.printStackTrace();//NOT REACHES EXCEPTION
}
}
Я отвечаю на ваш вопрос другим вопросом:
Почему метод
finalize
не должен быть защищен?
В общем, вы должны стараться сохранять как можно большую конфиденциальность. Вот что такое инкапсуляция. В противном случае вы можете сделать все общедоступным
. finalize
не может быть частным
(поскольку производные классы должны иметь доступ к нему, чтобы иметь возможность его переопределить), поэтому он должен быть как минимум защищенным
, но зачем предоставлять больше доступа, когда это нежелательно?
После более внимательного прочтения вашего комментария, я думаю, теперь я понял вашу главную мысль. Я думаю, что ваша точка зрения заключается в том, что, поскольку все происходит от java.lang.Object
и, следовательно, обращается к его защищенным
членам, это не будет иметь никакого значения для него (или любого метода в java.lang.Object
в этом отношении) должен быть общедоступным
в отличие от защищенного
. Лично я считаю это недостатком дизайна Java. Это действительно исправлено в C #. Проблема не в том, почему finalize
защищен. Это нормально. Реальная проблема заключается в том, что вы не должны иметь возможность вызывать защищенные методы в базовом классе через ссылку на объект типа базового класса. У Эрика Липперта есть запись в блоге , в которой обсуждается, почему разрешение такого рода доступа защищенным членам является плохой идеей, которая более подробно рассматривается в этом вопросе в разделе «Переполнение стека».
Возражения против finalize ()
Остерегайтесь ошибок в приведенных выше утверждениях, я немного устал: -)
Просмотрите эту ссылку , в которой это обсуждается.
В принципе, было бы наиболее разумно сделать его частным
, поскольку он должен вызываться только JVM (сборщиком мусора). Но для того, чтобы позволить подклассу вызывать родительский метод finalize ()
как часть его finalize ()
, он должен быть защищен
.
( Edit - И просто общее предостережение - использование метода finalize () обычно не рекомендуется, поскольку нет никакого способа гарантировать, что он когда-либо будет вызван. Хотя это не означает, что вы: у меня никогда не будет случая использовать его - это просто редкость.)
Почему доступ метода finalize () модификатор выполнен защищенным. Почему не может быть публичным?
Он не является публичным, потому что на него не должен ссылаться никто, кроме JVM. Однако он должен быть защищен, чтобы его могли переопределить подклассы, которым необходимо определить его поведение.
Если я называю это дважды в своей программе, внутренне что происходит?
Вы можете называть это все, что хотите, это просто метод в конце концов. Однако, подобно public static void main (String [] args)
, она имеет особое значение для JVM
Будет ли сборщик мусора называть это снова?
Да
-121--1278239-Аннотированный тэг фактически является объектом тэга. Имеет автора, описание, метку времени и указывает на фиксацию.
Облегченный тэг указывает на фиксацию и не содержит никакой другой информации. У него больше общего с ветвлением, чем с маркированием.
-121--2418398- Это не открытый
(или доступ по умолчанию), потому что он предназначен для вызова JVM внутри, когда объект собирается мусором - он не предназначен для вызова чем-либо другим. И это не частный
, потому что он должен быть переопределен, и вы не можете переопределить частные методы.
Если я называю это дважды в своей программе, что происходит внутри страны? Уилл сборщик мусора назовет это Опять же?
Наверное, да, но трудно представить себе сценарий, где это имело бы какой-либо смысл - точка finalize ()
делать очистку, когда объект собирается мусором. И он даже не делает этого хорошо, так что это действительно то, чего вы должны избежать вообще, а не экспериментировать.
Также я узнал, что метод finalize() вызывается только один раз. Если я вызову его дважды в моей программе, внутренне что произойдет?
Возможно, вы спрашиваете это под впечатлением от ~деструкторов C++. В java метод finalize() не делает никакой магии (например, не очищает память). Предполагается, что он должен вызываться сборщиком мусора. Но не наоборот.
Я рекомендую вам прочитать соответствующую главу в книге Джошуа Блоха "Эффективная Java". Там говорится, что использование финализаторов - плохая практика, которая может привести к проблемам с производительностью и другим проблемам, и есть только несколько случаев, когда их следует использовать. Глава начинается следующими словами:
Финализаторы непредсказуемы, часто опасны и, как правило, не нужны.
finalize () используется JVM только для очистки ресурсов при сборе объекта. Для класса разумно определить, какие действия должны выполняться над коллекцией, для чего ему может потребоваться доступ к super.finalize (). На самом деле для внешнего процесса не имеет смысла вызывать finalize (), поскольку внешний процесс не контролирует, когда объект собирается.
Часть о том, что finalize()
вызывается только один раз, относится только к вызовам из GC. Вы можете представить объект как имеющий скрытый флаг "finalize()
был вызван GC", и GC проверяет этот флаг, чтобы знать, что делать с объектом. На флаг никак не влияют ваши собственные ручные вызовы finalize()
.
По поводу финализации прочитайте эту статью Ханса Бёма (известного своей работой по сборке мусора). Это очень интересная статья о финализации; в частности, Боэм объясняет, почему финализация обязательно должна быть асинхронной. Следствием этого является то, что хотя финализация является мощным инструментом, она очень редко бывает подходящим инструментом для конкретной работы.
Почему модификатор доступа метода finalize () сделан как защищенный. Почему не может быть общедоступным?
Он не является общедоступным, потому что он не должен запускаться кем-либо, кроме JVM. Однако он должен быть защищен, чтобы его могли переопределить подклассы, которым необходимо определять его поведение.
Если я вызову его дважды в своей программе, что происходит внутри?
Вы можете вызывать это как хотите, в конце концов, это всего лишь метод. Однако, как и public static void main (String [] args)
, он имеет особое значение для JVM
Будет ли сборщик мусора вызывать это снова ?
Да
]