考虑以下代码段:
class A{ /* assume static and non static block are here */ }
class B extends A{ /* assume static and non static block are here */ }
在主方法中,
new B();
所以初始化的顺序是:
- 类A的静态成员初始化
- 类B的静态成员初始化
- 类A的非静态成员初始化
- 然后执行构造函数A中的代码
- 类B的非静态成员初始化
- 然后执行构造函数B中的代码
现在看看这段代码,
class A{
A(){
this.m(); //line 1
}
void m(){
System.out.println("A.m()");
}
}
class B extends A{
void m(){
System.out.println("B.m()");
}
}
在主方法中,
new B();
当构造函数A的代码正在执行时,它只能看到类A中的方法m,因为类B的非静态成员尚未初始化(根据我提到的顺序)。 然而结果是“B.m()”。 (子类的方法已经执行) 考虑到我提到的顺序,有人可以解释这里发生了什么(方法覆盖)吗?
最佳答案
When the code of constructor A is being executed, it can only see the method m in class A since non static members hasn't been initialized yet for class B (according to the order I mentioned).
您假设方法是已初始化的“非静态成员”的一部分。事实并非如此 - 这实际上是 B
中的 fields 在 A
构造函数完成时被初始化的问题。
一旦在 Java 中创建了一个对象,它的类型就被设置并且永远不会改变。为所有字段分配了足够的空间 - 但这些字段实际上是从继承层次结构的顶部向下初始化的。
所以是的,如果您从构造函数调用重写的方法,它将在它想要使用的某些字段未初始化的上下文中执行 - 因此您应该尽可能避免这样做。
关于java - java中的方法覆盖和继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18190825/