何时初始化实例变量并分配值? [英] When do instance variables get initialized and values assigned?
问题描述
实例变量什么时候初始化?是在构造函数块完成之后还是之前?
When does the instance variable get initialized? Is it after the constructor block is done or before it?
考虑这个例子:
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();
}
}
输出:
父构造器
子初始化()
父初始化()
子构造函数
属性 1 : 100
属性 2:空
属性 1 & 的内存是什么时候2 分配在堆中?
When are the memory for the atribute 1 & 2 allocated in the heap ?
想知道为什么属性 2 为 NULL 吗?
Curious to know why is attribute 2 is NULL ?
是否有任何设计缺陷?
推荐答案
当内存为属性 1 &2 是在堆中分配的吗?
When the memory for the atribute 1 & 2 are allocated in the heap ?
在java.lang.Object
构造函数被调用之前,当调用new
操作符时,为整个对象分配内存.内存是为 init
中的单个 Integer
实例分配的,但是为单个属性分配内存是没有意义的——只有整个对象.
The memory for the object as a whole is allocated when the new
operator is invoked, before the java.lang.Object
constructor is entered. Memory is allocated for individual Integer
instances in init
, but there is no point when memory is allocated for individual properties -- only whole objects.
想知道为什么属性 2 为 NULL 吗?
Curious to know why is attribute 2 is NULL ?
在超构造函数中调用了init
方法,所以给attribute2
赋值new Integer(200)
,然后子类构造函数就是调用它按照它们在源代码中出现的顺序应用属性初始值设定项.这一行
The init
method is called in the super constructor, so attribute2
is assigned new Integer(200)
, and then the subclass constructor is invoked which applies property initializers in the order they appear in the source code. This line
private Integer attribute2 = null;
将 init()
分配的值覆盖为 null
.
overwrites the value assigned by init()
to null
.
如果您添加对
System.out.println("attribute 2 : " +attribute2);
在您调用 super();
之后,这将变得显而易见.
right after your call to super();
then this will become apparent.
是否有任何设计缺陷?
在基类完成初始化之前调用子类方法是危险的.子类可能依赖基类的不变量来保护自己的不变量,如果基类的构造函数没有完成,那么它的不变量可能不成立.
Calling sub-class methods before the base class has finished initializing is dangerous. The sub-class might rely on its base-class's invariants to protect its own invariants, and if the base-class constructor has not completed, then its invariants may not hold.
这也可能让 C++ 程序员等感到困惑,他们希望从基类调用 init
来调用基类的版本,因为 C++ 会在输入构造函数时重写 vtable 指针.
This is also likely to confuse C++ programmers and the like who would expect a call to init
from the base class to invoke the base class's version since C++ rewrites the vtable pointer as constructors are entered.
请参阅Java 语言规范了解所有信息血腥的细节.
See The Java Language Specification for all the gory details.
这篇关于何时初始化实例变量并分配值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!