2012-09-06 71 views
7

当doees实例变量被初始化?它是在构造器块完成之后还是在它之前?什么时候实例变量被初始化并赋值?

考虑这个例子:

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:

父类的构造

儿童的init()

父初始化()

儿童构造

属性1:100

属性2:空


  1. 当记忆为属性1 & 2分配在堆中?

  2. 想知道为什么属性2是NULL?

  3. 是否有任何设计缺陷?

+0

顺便说一句,Java实例变量的术语是“field”。 –

回答

10

当用于属性附加伤害1 & 2存储器堆中分配?

在输入java.lang.Object构造函数之前调用new运算符时,将分配整个对象的内存。内存分配给init中的个人Integer实例,但内存分配给各个属性 - 仅限整个对象时没有意义。

想知道为什么属性2是NULL?

init方法被称为在超构造,所以attribute2分配new Integer(200),然后将子类构造函数被调用,其在它们出现在源代码中的顺序应用属性初始化。这条线

private Integer attribute2 = null; 

覆盖由init()分配给null的值。

如果您的来电​​之后添加到

System.out.println("attribute 2 : " +attribute2); 

一个电话,那么这将是显而易见的。

是否有任何设计缺陷?

在基类完成初始化之前调用子类方法是危险的。子类可能依赖其基类不变量来保护自己的不变量,如果基类构造函数未完成,则其不变量可能不成立。

这也很可能会混淆C++程序员等等,因为C++在输入构造函数时重写了vtable指针,所以期望从基类调用init来调用基类的版本。

查看The Java Language Specification了解所有血淋淋的细节。

+0

感谢Mike,Design:我的意思是让init()在它自己的构造函数之前执行是一个很好的习惯。因为它在这里击败了我的孩子init()的目的。你对此有什么想法? – AKh

+0

另外,让您的实例变量初始化为null还是不好? – AKh

+0

@AKh调用可以被子类重写的构造函数中的方法通常是不好的做法。你不希望你的子课堂能够打破你的课堂。 –

1

消耗这里提供的答案和链接后是我的消化观察:


这里是流量:

  1. 进入儿童类的构造函数。子(){...}

  2. 调用显式超级()[调用父类构造函数]。

  3. 输入父(){...}类的构造函数

  4. 调用隐超()调用对象类构造函数]

  5. 输入对象(){}(没有超级构造函数调用)

  6. 超类构造函数的递归调用在此处结束。

    为Object类的构造函数

  7. 现在,在父类的构造...实例初始化和父类的实例变量初始化

  8. 返回被执行。父类的构造函数的

  9. 剩下的就是执行和儿童类构造函数返回

  10. 现在。实例初始值设定项和Child类的实例变量初始值设定项被执行。

  11. 然后执行Child类构造函数的其余部分并完成对象初始化过程。因为

    1. attribute2分配了值200 @步骤9.
    2. 但是重写为NULL在步骤10


原因attribute2是NULL 有没有任何设计缺陷?

作为Fabian Barney提到:::::调用可以被子类重写的构造函数中的方法通常是不好的做法。

当在堆中分配属性的内存时1 & 2? 还在搞清楚。欣赏任何指针。

感谢您的Mike和Fabian

相关问题