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

bra*_*boy 35 java finalize

出于好奇,

为什么finalize()方法的访问修饰符是作为protected.为什么不能呢public?有人可以解释我背后的具体原因吗?

此外,我开始知道该finalize()方法只被调用一次.如果我在程序内部调用它两次,会发生什么?垃圾收集器会再次调用它吗?

private void dummyCall() {
    try {
        finalize();
        finalize();
    } catch (Throwable e) {
        e.printStackTrace();//NOT REACHES EXCEPTION
    }
}
Run Code Online (Sandbox Code Playgroud)

Meh*_*ari 24

我用另一个问题回答你的问题:

为什么finalize方法不应该受到保护?

一般来说,你应该尽量保持私密性.这就是封装的全部内容.否则,你可以做出一切 public.finalize不能private(因为派生类应该能够访问它以便能够覆盖它),所以它至少应该是protected为什么在不可取的时候提供更多的访问权限?


在仔细阅读你的评论之后,我想我现在看到了你的要点.我认为你的观点是,因为一切都源于java.lang.Object并因此访问其protected成员,所以它(或任何相关的方法java.lang.Object)与之public相反不会有任何区别protected.就个人而言,我认为这是Java中的一个设计缺陷.这确实在C#中得到了修复.问题不finalize在于为什么受到保护.没关系.真正的问题是您不能通过基类类型的对象引用来调用基类中的受保护方法.Eric Lippert有一篇博客文章,讨论为什么允许这种对受保护成员的访问是一个坏主意,这个问题在Stack Overflow中进一步阐述.

  • @Johannes:因为抽象方法*必须被子类覆盖,并且你不能覆盖私有方法.因此,"私人抽象"在术语上会是矛盾的. (7认同)
  • @Johannes:你在说什么?这正是受保护方法的用途.私有是指不应被覆盖的事物. (4认同)
  • "隐藏"尽可能多的信息是抽象的本质. (2认同)
  • 哦,这很奇怪.就个人而言,我发现抽象方法显然不是私有的java的弱点.谁知道原因?它是否与脆弱的基类问题有关? (2认同)

Kev*_*vin 23

为什么finalize()方法的访问修饰符被设为受保护.为什么不能公开?

它不公开,因为除了JVM之外的任何人都不应该调用它.但是,它必须受到保护,以便可以由需要为其定义行为的子类覆盖它.

如果我在我的程序中调用它两次,内部发生了什么?

你可以随心所欲地调用它,毕竟它只是一种方法.但是,很像public static void main(String [] args),它对JVM具有特殊意义

垃圾收集器会再次调用它吗?


jos*_*efx 12

  • finalize意味着仅由gc调用,因此不需要公共访问
  • 确保finalize只被gc调用一次,自己调用它会打破这个保证,因为gc不会知道它.
  • 任何压倒一切的课程都可以公开,我认为由于上述原因这是不好的
  • finalize不应包含太多代码,因为finalize抛出的任何异常都可能会终止gc的终结器线程.

反对敲定()

  • 管理本机资源或需要调用dispose()或close()的任何资源可能导致很难找到错误,因为它们只会在jvm内存不足时释放,您应该手动释放资源.Finalize只应用于调试资源泄漏或手动管理资源过多的情况.
  • 将在gc的另一个线程中调用finalize,并可能导致资源锁定等问题.
  • 像WeakReference和ReferenceQueue这样的引用类是处理清理的另一种(相当复杂的)方法,可能与本机资源的finalize()有同样的问题.

小心上述陈述中的错误,我有点累了:-)