为什么我可以访问另一个包的其他子类中的 Finalize() 方法?

2024-02-11

我是 Java 新手,第一次尝试学习 Java。 我的简单问题是关于java.lang.Object 中的finalize() 方法。为什么我可以访问其他类中唯一的受保护方法,而不是其他受保护方法。我的导师告诉我,受保护仅在其类、同一包及其子类中具有作用域。Here https://stackoverflow.com/questions/215497/in-java-whats-the-difference-between-public-default-protected-and-private我读了这个。

有人可以解释一下 Finalize() 方法是否有任何特殊情况。我有一个不令人满意的答案为什么 Finalize () 受到保护here https://stackoverflow.com/questions/2291470/why-is-the-finalize-method-in-java-lang-object-protected我的代码如下:

//Creating Package Foo
package Foo;
class A
{
    protected finalize() 
    { 
        System.out.println("This is finalize method of Class A");
    }
}

// Creating Another Pacakage Foo1
package Foo1;
import Foo.*;
class B extends A
{
}
class C extends B
{
}
class D extends C
{
    public void foo() {
        C ob = new C();
        ob = null;
        System.gc(); // Why class A finalize() is getting call
    }
}

仅在 Finalize() 的情况下才会被调用,而在其他情况下则不会。 问我的导师,他拒绝回答,他说你犯了一些错误,我会看看,但他没有回复我。

请想想我正在学习java。也许我犯了一些大错误。


这按预期工作,我不认为finalize()方法的处理方式与 Java 中的任何其他方法不同。可以认为有点不同的是finalize()方法通常仅由 JVM 垃圾收集器本身调用,如JavaDoc http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#finalize%28%29:

当垃圾收集确定不再有对该对象的引用时,由该对象的垃圾收集器调用。

另请注意,Josh Bloch 强烈警告不要在:

终结器是不可预测的,通常很危险,而且通常是不必要的。它们的使用可能会导致行为不稳定、性能不佳和可移植性问题。终结器有一些有效的用途……但根据经验,您应该避免使用终结器。

考虑以下示例,该示例与您的示例类似:

具有重写的基类finalize() method.

public abstract class BaseClass {
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("BaseClass finalisation occured");
    }
}

不重写 Finalize 的子类:

public class SubClass extends BaseClass {
    public void foo() {
        System.out.println("SubClass Foo'd");
    }
}

以及一个具有基本 main 方法来运行所有内容的驱动程序类:

public class Driver {
    public static void main(String[] args) {
        SubClass sc = new SubClass();
        sc.foo();
        sc = null;
        System.gc();        
    }
}

我们得到的输出如下:

SubClass Foo'd
BaseClass finalisation occured

Java 方法查找(用非常简单的术语来说)是在当前类中查找任何方法,如果没有,则攀爬类层次结构,直到找到所需的方法。在上面的例子中,当foo()方法被调用SubClass对象,即SubClass类包含方法定义,以便使用实现,并且类层次结构不会向上爬。当。。。的时候finalize()方法被调用(因为System.gc()已被请求),该方法将首先在SubClass类,但因为它不包含实现finalize()它的父级(BaseClass) 被搜索。BaseClass确实包含一个实现finalize()因此使用它,并将一行打印到标准输出。

现在考虑一个覆盖的子子类finalize() again:

public class OverridenSubClass extends SubClass {
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("Overriden finalize called, which calls super's finalize first");
    }
}

并且稍微修改了一下Driver class:

public class Driver {

    public static void main(String[] args) {
        OverridenSubClass sc = new OverridenSubClass();
        sc.foo();
        System.out.println(sc.toString());
        sc = null;
        System.gc();
        System.exit(0);
    }
}

产生以下输出:

SubClass Foo'd
finalize.OverridenSubClass@7150bd4d
BaseClass finalisation occured
Overriden finalize called, which calls initial finalize first

希望这符合预期。这里需要注意的唯一有趣的事情是:

  1. 我们不覆盖toString()在我们的任何一个班级中,所以Object.toString()使用实现。
  2. 变量的类型sc不是决定所使用的方法实现的因素 - 它是实际的类型object引用者sc
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么我可以访问另一个包的其他子类中的 Finalize() 方法? 的相关文章

随机推荐