我是 Java 新手 我第一次尝试学习 Java。 我的简单问题是关于 java.lang.Object 中的 finalize() 方法。为什么我只能在我的其他类中访问这个 protected 方法,而不能访问其他 protected 方法。我的导师告诉我,protected 只在它的类、同一个包和它的子类中有作用域。 Here我读了这个。
有人可以解释一下 finalize() 方法有什么特殊情况吗?我有一个不满意为什么 finalize () protected 答案 here 我的代码如下:
//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 中所述。 :
Called by the garbage collector on an object when garbage collection determines that there are no more references to the object.
另请注意,Josh Bloch 强烈警告不要在 Effective Java 中使用终结器。 :
Finalizers are unpredictable, often dangerous, and generally unnecessary. Their use can cause erratic behaviour, poor performance, and portability problems. Finalizers have a few valid uses ... but as a rule of thumb you should avoid finalizers.
考虑以下与您的示例类似的示例:
具有覆盖的基类 finalize()
方法。
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
class 包含方法定义,以便使用实现,并且类层次结构不会向上攀升。当 finalize()
调用方法(因为已请求 System.gc()
),将首先在 SubClass
中查找该方法类,但因为它不包含 finalize()
的实现搜索其父级 ( BaseClass
)。 BaseClass
确实包含 finalize()
的实现所以它被使用,一行被打印到标准输出。
现在考虑一个重写 finalize()
的子子类再次:
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
类:
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
希望这符合预期。这里唯一需要注意的有趣的事情是:
- 我们不会覆盖
toString()
在我们的任何类(class)中,所以Object.toString()
使用实现。 - 变量类型
sc
不是决定使用的方法实现的因素 - 它是sc
引用的实际对象 的类型
关于java - 为什么我可以访问另一个包的其他子类中的 finalize() 方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17655366/