为什么 java.lang.Object 中的 finalize() 方法是“受保护的”?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2291470/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why is the finalize() method in java.lang.Object "protected"?
提问by bragboy
Out of curiosity,
出于好奇,
Why is the finalize()
method's access modifier is made as protected
. Why cant it be public
? Can someone explain me any specific reason behind this?
为什么将finalize()
方法的访问修饰符设为protected
. 为什么不能呢public
?有人可以向我解释这背后的任何具体原因吗?
Also, I came to know that finalize()
method is called only once. If I call it twice in my program internally, what is happening? Will the garbage collector call this again?
此外,我开始知道该finalize()
方法只被调用一次。如果我在我的程序内部调用它两次,会发生什么?垃圾收集器会再次调用它吗?
private void dummyCall() {
try {
finalize();
finalize();
} catch (Throwable e) {
e.printStackTrace();//NOT REACHES EXCEPTION
}
}
采纳答案by Mehrdad Afshari
I answer your question with another question:
我用另一个问题回答你的问题:
Why
finalize
method shouldn't be protected?
为什么
finalize
方法不应该受到保护?
In general, you should try to keep things as much private as possible. That's what encapsulation is all about. Otherwise, you could make everythingpublic
. finalize
can't be private
(since derived classes should be able to access it to be able to override it), so it should at least be protected
but why give out more access when it's not desirable?
一般来说,您应该尽量保持私密性。这就是封装的全部意义所在。否则,你可以制作一切public
。finalize
不能private
(因为派生类应该能够访问它以便能够覆盖它),所以它至少应该是,protected
但是为什么在不需要时提供更多访问权限?
After reading your comment more carefully, I guess I see your main point now. I think your point is since everything derives from java.lang.Object
and consequently accesses its protected
members, it wouldn't make any difference for it (or any method in java.lang.Object
for that matter) to be public
as opposed to protected
. Personally, I'd count this as a design flaw in Java. This is indeed fixed in C#. The problem is not why finalize
is protected. That's OK. The real issue is that you shouldn't be able to call protected methods in the base class through an object reference of the base class type. Eric Lippert has a blog entrydiscussing why allowing such kind of access to protected members is a bad idea which is further elaborated on Stack Overflow in this question.
更仔细地阅读您的评论后,我想我现在明白您的主要观点了。我觉得你的意思是,因为从一切导出java.lang.Object
,因此访问其protected
成员,它不会做它(或以任何方式任何区别java.lang.Object
为此事)是public
相对于protected
。就个人而言,我认为这是 Java 中的一个设计缺陷。这确实在 C# 中得到了修复。问题不finalize
在于为什么受到保护。没关系。真正的问题是您不应该能够通过基类类型的对象引用调用基类中的受保护方法。Eric Lippert 有一篇博客文章讨论了为什么允许对受保护成员进行此类访问是一个坏主意,在此问题中进一步详细说明了堆栈溢出。
回答by froadie
Check out this linkwhich discusses it.
查看讨论它的这个链接。
Basically, it would make the most sense for it to be private
, as it should only be called by the JVM (garbage collector). But in order to allow a subclass to call the parent finalize()
method as part of its finalize()
, it has to be protected
.
基本上,它是最有意义的private
,因为它应该只由 JVM(垃圾收集器)调用。但是为了允许子类调用父finalize()
方法作为其一部分finalize()
,它必须是protected
.
(Edit- And just a general caution - use of the finalize() method is generally discouraged as there's no way of ensuring that it will ever be called. Although that doesn't mean that you'll never have occasion to use it - it's just rare.)
(编辑- 只是一般警告 - 通常不鼓励使用 finalize() 方法,因为没有办法确保它会被调用。虽然这并不意味着你永远不会有机会使用它 - 它是只是很少见。)
回答by Kevin
Why is the finalize() method's access modifier is made as protected. Why cant it be public?
为什么 finalize() 方法的访问修饰符被设置为受保护的。为什么不能公开?
It is not public because it shouldn't be invoked by anyone other than the JVM. However, it must be protected so that it can be overridden by subclasses who need to define behavior for it.
它不是公开的,因为它不应该被 JVM 以外的任何人调用。但是,它必须受到保护,以便需要为其定义行为的子类可以覆盖它。
If i call it twice in my program, internally what is happening?
如果我在我的程序中调用它两次,内部发生了什么?
You can call it all you want, its just a method after all. However, much like public static void main(String [] args)
, it has special meaning to the JVM
你可以随意调用它,毕竟它只是一种方法。但是,很像public static void main(String [] args)
,它对 JVM 具有特殊意义
Will the garbage collector call this again?
垃圾收集器会再次调用它吗?
Yes
是的
回答by Michael Borgwardt
It's not public
(or default access) because it's meant to be called by the JVM internally when the object is garbage collected - it's notmeant to be called by anything else. And it's not private
because it's meant to be overridden and you can't override private methods.
它不是public
(或默认访问),因为它意味着当对象被垃圾收集时由 JVM 在内部调用 - 它并不意味着被其他任何东西调用。并且这不是private
因为它意味着要被覆盖并且您不能覆盖私有方法。
If i call it twice in my program, internally what is happening? Will the garbage collector will call this again?
如果我在我的程序中调用它两次,内部发生了什么?垃圾收集器会再次调用它吗?
Probably yes, but it's hard to imagine a scenario where this would make any kind of sense - the point of finalize()
is to do cleanup when an object is garbage collected. And it doesn't even do that well, so it's really something you should avoid altogether rather than experiment with.
可能是的,但很难想象这种情况会有任何意义 -finalize()
目的是在对象被垃圾收集时进行清理。它甚至没有那么好,所以它真的是你应该完全避免而不是尝试的东西。
回答by Steve B.
finalize() is only used by the JVM to clean up resources when the object is collected. It's reasonable for a class to define what actions should be taken on collection, for which it may need to access super.finalize(). It doesn't really make sense for an outside process to call finalize(), since an outside process doesn't have control over when the object is collected.
finalize() 仅被 JVM 用于在收集对象时清理资源。一个类定义应该对集合采取什么操作是合理的,它可能需要访问 super.finalize()。外部进程调用 finalize() 真的没有意义,因为外部进程无法控制何时收集对象。
回答by Roman
Also, I came to know that finalize() method is called only once. If i call it twice in my program, internally what is happening?
另外,我开始知道 finalize() 方法只被调用一次。如果我在我的程序中调用它两次,内部发生了什么?
You probably ask this under impression of C++ ~destructors. In java finalize () method doesn't do any magic (like clearing memory). It's supposed to be called by garbage collector. But not vice versa.
你可能会在 C++ ~destructors 的印象中问这个问题。在 java finalize() 方法中没有做任何魔法(比如清除内存)。它应该由垃圾收集器调用。但反之则不然。
I recommend you to read correspondent chapter in Joshua Bloch's "Effective Java". It says that using finalizers is a bad practice and can cause performance and other issues, and there are only several cases when they should be used. The chapter begins with next words:
我建议您阅读 Joshua Bloch 的“Effective Java”中的相应章节。它说使用终结器是一种不好的做法,会导致性能和其他问题,并且只有几种情况应该使用它们。本章以接下来的话开始:
Finalizers are unpredictable, often dangerous, and generally unnecessary.
终结器是不可预测的,通常是危险的,而且通常是不必要的。
回答by josefx
- finalize is meant to be called by the gc onlyand as such does not require public access
- finalize is guaranteed to be called only once by the gc, calling it yourself will break this guarantee, as the gc wont know about it.
- Any overriding class can make finalize public, which I believe is bad for the above reasons
- finalize should not contain much code, as any exception thrown by finalize may kill the finalizer thread of the gc.
- finalize 只能由 gc 调用,因此不需要公共访问
- finalize 保证只被 gc调用一次,你自己调用它会破坏这个保证,因为 gc 不会知道它。
- 任何覆盖类都可以使 finalize 公开,我认为由于上述原因这是不好的
- finalize 不应包含太多代码,因为 finalize 抛出的任何异常都可能杀死 gc 的终结器线程。
Rant against finalize()
反对 finalize()
- Managing native resources or any resource which requires dispose() or close() to be called may cause hard to find bugs as they will only be released when the jvm runs out of memory, you should release resources manually. Finalize should only be used for debugging resource leaks or for cases where managing resources manually is too much work.
- finalize will be called in an additional thread of the gc and may cause problems with resource locking and so on.
- the reference classes like WeakReference and ReferenceQueue are an alternative (rather complex) way to deal with cleanup and may have the same problems as finalize() for native resources.
- 管理本机资源或任何需要调用 dispose() 或 close() 的资源可能会导致难以发现错误,因为它们只会在 jvm 内存不足时释放,您应该手动释放资源。Finalize 应该只用于调试资源泄漏或手动管理资源工作量太大的情况。
- finalize 将在 gc 的附加线程中调用,并且可能会导致资源锁定等问题。
- 像 WeakReference 和 ReferenceQueue 这样的引用类是处理清理的另一种(相当复杂的)方法,并且可能与本地资源的 finalize() 存在相同的问题。
Beware of errors in the above statements, I'm a bit tired :-)
注意上面的语句中的错误,我有点累:-)
回答by Thomas Pornin
The part about finalize()
being called only once applies only to the calls from the GC. You can imagine the object as having a hidden flag "finalize()
was called by the GC", and the GC checking that flag to know what to do with the object. The flag is not impacted in any way by your own handmade calls to finalize()
.
finalize()
仅被调用一次的部分仅适用于来自 GC 的调用。你可以把对象想象成有一个隐藏的标志“finalize()
被 GC 调用”,并且 GC 检查该标志以了解如何处理该对象。该标志不会以任何方式受到您自己手动调用finalize()
.
On finalization, read this articlefrom Hans Boehm (who is well-known for his work on garbage collection). This is an eye-opener about finalization; in particular, Boehm explains why finalization is necessarily asynchronous. A corollary is that while finalization is a powerful tool, it is very rarely the right tool for a given job.
关于定稿,请阅读Hans Boehm(他在垃圾收集方面的工作而闻名)的这篇文章。这是关于定稿的大开眼界;Boehm 特别解释了为什么终结必须是异步的。一个推论是,虽然定稿是一个强大的工具,但对于给定的工作来说,它很少是正确的工具。
回答by meerut
I think the reason why finalize
is protected would be that maybe it's overridden by some classes in the JDK, and those overridden methods are called by JVM.
我认为finalize
受保护的原因可能是它被 JDK 中的某些类覆盖,而那些被覆盖的方法被 JVM 调用。