Почему является завершение () методом в java.lang. Объект “защищен”?

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

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

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

private void dummyCall() {
    try {
        finalize();
        finalize();
    } catch (Throwable e) {
        e.printStackTrace();//NOT REACHES EXCEPTION
    }
}
35
задан bragboy 7 September 2011 в 12:36
поделиться

8 ответов

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

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

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


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

24
ответ дан 27 November 2019 в 06:58
поделиться
  • finalize предназначен для вызова только gc и, как таковой, не требует открытого доступа
  • finalize гарантированно вызывается только один раз контроллером gc , вызов его самостоятельно нарушит эта гарантия, поскольку gc об этом не узнает.
  • Любой замещающий класс может сделать finalize общедоступным, что я считаю плохим по указанным выше причинам.
  • finalize не должен содержать много кода, поскольку любое исключение, созданное finalize, может убить поток финализатора gc.

Возражения против finalize ()

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

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

12
ответ дан 27 November 2019 в 06:58
поделиться

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

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

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

3
ответ дан 27 November 2019 в 06:58
поделиться

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

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

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

Вы можете называть это все, что хотите, это просто метод в конце концов. Однако, подобно public static void main (String [] args) , она имеет особое значение для JVM

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

Да

-121--1278239-

Аннотированный тэг фактически является объектом тэга. Имеет автора, описание, метку времени и указывает на фиксацию.

Облегченный тэг указывает на фиксацию и не содержит никакой другой информации. У него больше общего с ветвлением, чем с маркированием.

-121--2418398-

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

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

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

2
ответ дан 27 November 2019 в 06:58
поделиться

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

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

Я рекомендую вам прочитать соответствующую главу в книге Джошуа Блоха "Эффективная Java". Там говорится, что использование финализаторов - плохая практика, которая может привести к проблемам с производительностью и другим проблемам, и есть только несколько случаев, когда их следует использовать. Глава начинается следующими словами:

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

1
ответ дан 27 November 2019 в 06:58
поделиться

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

1
ответ дан 27 November 2019 в 06:58
поделиться

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

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

3
ответ дан 27 November 2019 в 06:58
поделиться

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

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

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

Вы можете вызывать это как хотите, в конце концов, это всего лишь метод. Однако, как и public static void main (String [] args) , он имеет особое значение для JVM

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

Да

]
23
ответ дан 27 November 2019 в 06:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: