简体   繁体   English

为什么java.lang.Object中的finalize()方法受到“保护”?

[英]Why is the finalize() method in java.lang.Object “protected”?

Out of curiosity, 出于好奇,

Why is the finalize() method's access modifier is made as protected . 为什么将finalize()方法的访问修饰符设置为protected Why cant it be public ? 为什么不能public Can someone explain me any specific reason behind this? 有人可以向我解释这背后的任何具体原因吗?

Also, I came to know that finalize() method is called only once. 另外,我知道finalize()方法仅被调用一次。 If I call it twice in my program internally, what is happening? 如果我在程序内部两次调用它,会发生什么情况? Will the garbage collector call this again? 垃圾收集器会再次调用吗?

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

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 everything public . 否则,您可以将所有内容 public 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? 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 . 我认为您的意思是,由于所有内容都源自java.lang.Object并因此访问其protected成员,因此将其public (或与此相关的java.lang.Object任何方法)没有任何区别protected Personally, I'd count this as a design flaw in Java. 我个人认为这是Java的设计缺陷。 This is indeed fixed in C#. 这确实在C#中已修复。 The problem is not why finalize is protected. 问题不是为什么finalize受保护。 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 entry discussing why allowing such kind of access to protected members is a bad idea which is further elaborated on Stack Overflow in this question . 埃里克·利珀特(Eric Lippert)的博客条目讨论了为什么允许这种方式访问​​受保护成员不是一个好主意, 对此问题在“堆栈溢出”中作了进一步阐述

Why is the finalize() method's access modifier is made as protected. 为什么finalize()方法的访问修饰符被设置为保护状态。 Why cant it be public? 为什么不能公开?

It is not public because it shouldn't be invoked by anyone other than the JVM. 它不是公共的,因为它不应被JVM之外的任何人调用。 However, it must be protected so that it can be overridden by subclasses who need to define behavior for it. 但是,必须对其进行保护,以便需要定义其行为的子类可以覆盖它。

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

  • finalize is meant to be called by the gc only and as such does not require public access finalize只能由gc调用,因此不需要公共访问
  • 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. finalize保证仅由gc调用一次,您自己调用它会破坏此保证,因为gc对此一无所知。
  • 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不应包含太多代码,因为finalize引发的任何异常都可能杀死gc的finalizer线程。

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. 管理本机资源或需要调用dispose()或close()的任何资源可能会导致难以发现错误,因为这些错误仅在jvm内存不足时才被释放,您应该手动释放资源。 Finalize should only be used for debugging resource leaks or for cases where managing resources manually is too much work. Finalize仅应用于调试资源泄漏或用于手动管理资源的工作过多的情况。
  • finalize will be called in an additional thread of the gc and may cause problems with resource locking and so on. finalize将在gc的附加线程中调用,并可能导致资源锁定等问题。
  • 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. 像WeakReference和ReferenceQueue这样的引用类是处理清除的另一种方法(相当复杂),并且可能与本机资源的finalize()一样。

Beware of errors in the above statements, I'm a bit tired :-) 当心上面声明中的错误,我有点累:-)

Check out this link which 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). 基本上,将它设为private是最有意义的,因为它只能由JVM(垃圾收集器)调用。 But in order to allow a subclass to call the parent finalize() method as part of its finalize() , it has to be protected . 但是为了允许子类在其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()方法。尽管这并不意味着您永远不会有使用它的方法-很少见。)

The part about finalize() being called only once applies only to the calls from the GC. 关于finalize()仅被调用一次的部分仅适用于来自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. 您可以想象该对象具有隐藏标志“ GC调用了finalize() ”,然后GC检查该标志以了解如何处理该对象。 The flag is not impacted in any way by your own handmade calls to finalize() . 您自己手工调用finalize()不会对标志产生任何影响。

On finalization, read this article from Hans Boehm (who is well-known for his work on garbage collection). 完成后,请阅读Hans Boehm(以垃圾收集工作而闻名的文章 )。 This is an eye-opener about finalization; 这对完成工作大开眼界。 in particular, Boehm explains why finalization is necessarily asynchronous. Boehm特别说明了为什么终止必须是异步的。 A corollary is that while finalization is a powerful tool, it is very rarely the right tool for a given job. 一个必然的结论是,虽然最终确定是一个强大的工具,但对于给定的工作而言,它很少是正确的工具。

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 not meant to be called by anything else. 它不是public (或默认访问权限),因为它是在对象被垃圾回收时由JVM内部调用的,而不是由其他任何东西调用的。 And it's not private because it's meant to be overridden and you can't override private methods. 而且它不是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. 可能是的,但是很难想象会有什么意义的情况finalize()的目的是在垃圾回收对象时进行清理。 And it doesn't even do that well, so it's really something you should avoid altogether rather than experiment with. 而且它甚至还不能很好地完成工作,因此,您确实应该完全避免而不是进行试验。

我认为finalize被保护的原因是,它可能被JDK中的某些类所覆盖,而那些被覆盖的方法被JVM调用。

finalize() is only used by the JVM to clean up resources when the object is collected. 当对象被收集时,JVM仅使用finalize()来清理资源。 It's reasonable for a class to define what actions should be taken on collection, for which it may need to access super.finalize(). 一个类定义在集合上应该采取什么动作是合理的,它可能需要为此访问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()确实没有意义,因为外部进程无法控制何时收集对象。

Also, I came to know that finalize() method is called only once. 另外,我知道finalize()方法仅被调用一次。 If i call it twice in my program, internally what is happening? 如果我在程序中两次调用它,内部会发生什么?

You probably ask this under impression of C++ ~destructors. 您可能会在C ++〜析构函数的印象下问这个问题。 In java finalize () method doesn't do any magic (like clearing memory). 在Java中,finalize()方法没有任何作用(例如清除内存)。 It's supposed to be called by garbage collector. 应该由垃圾收集器调用。 But not vice versa. 但反之亦然。

I recommend you to read correspondent chapter in Joshua Bloch's "Effective Java". 我建议您阅读Joshua Bloch的“ 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: 本章以以下几句话开头:

Finalizers are unpredictable, often dangerous, and generally unnecessary. 终结器是不可预测的,通常很危险,而且通常是不必要的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么在 java.lang.Object 中保护了 clone() 方法? - Why is the clone() method protected in java.lang.Object? 可以在子类的对象上调用受保护的方法而不会覆盖它们。 为什么java.lang.Object中的clone方法不同? - Protected methods can be called on the object of subclass without overriding. Why it's different for clone method in java.lang.Object? 实现克隆方法 - 错误 java:clone() 在 java.lang.Object 中具有受保护的访问权限 - Implementing clone method - Error java: clone() has protected access in java.lang.Object 如何修复proguard警告'找不到引用的方法'用于类java.lang.Object的现有方法'clone'和'finalize' - how to fix proguard warning 'can't find referenced method' for existing methods 'clone' and 'finalize' of class java.lang.Object 在java.lang.Object类中拥有受保护方法的目的是什么? - What is the purpose of having protected methods in java.lang.Object class? 为什么不能克隆java.lang.Object? - Why java.lang.Object can not be cloned? 为什么java.lang.Cloneable不会覆盖java.lang.Object中的clone()方法? - Why does java.lang.Cloneable not override the clone() method in java.lang.Object? Java8:为什么禁止为java.lang.Object中的方法定义默认方法 - Java8: Why is it forbidden to define a default method for a method from java.lang.Object 为什么只有克隆和完成是对象校准中的受保护方法? - why only clone and finalize are protected method in object calss? java.lang.Object 的受保护方法如何保护子类? - How are java.lang.Object's protected methods protected from subclasses?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM