AKh*_*AKh 9 java inheritance abstract-class object instance
当doees实例变量初始化时?是在构造函数块完成之后还是之前?
考虑这个例子:
public abstract class Parent {
public Parent(){
System.out.println("Parent Constructor");
init();
}
public void init(){
System.out.println("parent Init()");
}
}
Run Code Online (Sandbox Code Playgroud)
public class Child extends Parent {
private Integer attribute1;
private Integer attribute2 = null;
public Child(){
super();
System.out.println("Child Constructor");
}
public void init(){
System.out.println("Child init()");
super.init();
attribute1 = new Integer(100);
attribute2 = new Integer(200);
}
public void print(){
System.out.println("attribute 1 : " +attribute1);
System.out.println("attribute 2 : " +attribute2);
}
}
Run Code Online (Sandbox Code Playgroud)
public class Tester {
public static void main(String[] args) {
Parent c = new Child();
((Child)c).print();
}
}
Run Code Online (Sandbox Code Playgroud)
父构造函数
子init()
父Init()
儿童构造函数
属性1:100
属性2:null
当在堆中分配属性1和2的内存时?
很想知道为什么属性2是NULL?
有任何设计缺陷吗?
Mik*_*uel 11
当在堆中分配属性1和2的内存时?
在new
调用运算符之前,在输入java.lang.Object
构造函数之前,将分配整个对象的内存.内存是为各个Integer
实例分配的init
,但是没有必要为各个属性分配内存 - 只有整个对象.
很想知道为什么属性2是NULL?
该init
方法在超级构造函数中调用,因此attribute2
被赋值new Integer(200)
,然后调用子类构造函数,它按照它们在源代码中出现的顺序应用属性初始值设定项.这条线
private Integer attribute2 = null;
Run Code Online (Sandbox Code Playgroud)
覆盖由init()
to 分配的值null
.
如果你添加一个电话
System.out.println("attribute 2 : " +attribute2);
Run Code Online (Sandbox Code Playgroud)
在你打电话super();
之后,这将变得明显.
有任何设计缺陷吗?
在基类完成初始化之前调用子类方法是危险的.子类可能依赖于它的基类的不变量来保护它自己的不变量,如果基类构造函数没有完成,那么它的不变量可能不成立.
这也可能会混淆C++程序员之类的人,他们希望init
从基类调用来调用基类的版本,因为C++会在输入构造函数时重写vtable指针.
有关所有血腥细节,请参阅Java语言规范.