实例变量什么时候初始化?是在构造函数块完成之后还是之前?
考虑这个例子:
public abstract class Parent {
public Parent(){
System.out.println("Parent Constructor");
init();
}
public void init(){
System.out.println("parent Init()");
}
}
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);
}
}
public class Tester {
public static void main(String[] args) {
Parent c = new Child();
((Child)c).print();
}
}
OUTPUT:
父构造函数
子进程初始化()
父级初始化()
子构造函数
属性 1 : 100
属性 2:空
-
属性 1 和 2 的内存何时在堆中分配?
-
很想知道为什么属性 2 是 NULL ?
-
是否存在任何设计缺陷?
属性 1 和 2 的内存何时在堆中分配?
当对象作为一个整体分配内存时new
运算符被调用之前java.lang.Object
输入构造函数。内存分配给个人Integer
中的实例init
,但是为单个属性分配内存是没有意义的——只为整个对象分配内存。
很想知道为什么属性 2 是 NULL ?
The init
方法在超级构造函数中被调用,所以attribute2
被安排了new Integer(200)
,然后调用子类构造函数,该构造函数按照属性初始值设定项在源代码中出现的顺序应用它们。这条线
private Integer attribute2 = null;
覆盖分配的值init()
to null
.
如果您添加一个呼叫
System.out.println("attribute 2 : " +attribute2);
在您致电后super();
那么这就会变得明显。
是否存在任何设计缺陷?
在基类完成初始化之前调用子类方法是危险的。子类可能依赖其基类的不变量来保护其自己的不变量,并且如果基类构造函数尚未完成,则其不变量可能不成立。
这也可能会让 C++ 程序员等人感到困惑,他们希望调用init
从基类调用基类的版本,因为 C++ 在输入构造函数时重写 vtable 指针。
See Java 语言规范 http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.5对于所有血淋淋的细节。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)