java初始化构造函数调用顺序

类初始化时构造函数调用顺序:

  (1)初始化对象的存储空间为零或null值;
  (2)调用父类构造函数;
  (3)按顺序分别调用类成员变量和实例成员变量的初始化表达式;
  (4)调用本身构造函数

例子:
public class Dollar extends Money{
     Rmb r=new Rmb()
     public Dollar(){
      System.out.println("Dollar is construct!");
     }
     public static void main(String[] args){

      new Dollar();  

   }
}

class Money{
 public Money(){
  System.out.println("Money is construct");
 }
}

class Rmb{
 public Rmb(){
  System.out.println("RMB is construct");
 }
}

输出结果:
Money is construct
RMB is construct
Dollar is construct!

 

我们再自己写一个程序,以测试运行顺序:
 
 


输出结果:

   说明此时的运行顺序为:

  1.    父类类成员变量
  2.    父类静态块
  3.    自身类成员变量
  4.    自身静态块
  5.    父类实例成员变量
  6.    父类块
  7.    父类构造器
  8.    自身实例成员变量
  9.    自身块
  10.    自身构造器 

 再来看下伯乐在线小组的一个热门讨论帖:

 

 

携程 Java 工程师的一道面向对象面试题

public class Base {

private String baseName = "base";

  public Base() {

    callName();

  }

public void callName() {

  System.out.println(baseName);

}

static class Sub extends Base {

  private String baseName = "sub";

  public void callName() {

    System.out.println(baseName);

  }

}

  public static void main(String[] args) {

    Base b = new Sub();

  }

}

 

求这段程序的输出。

 

未老莫还乡 的评论:

 

【不要在构造器里调用可能被重载的虚方法,这是极度危险的】。构造器的初始化顺序大概是 父类静态块 子类静态块 父类初始化语句 父类构造函器 子类初始化语句 子类构造器。父类构造器执行的时候,调用了子类的重载方法,然而子类的类字段还在刚初始化的阶段,刚完成内存布局,只能输出null。

ihuning 的精华评论:

看我大师归来:

 

1. Base b = new Sub();

 

2. Base b = 直接忽略,从 new Sub();开始

 

3. 类加载器加载 Base,Sub 类到jvm;

 

4. 为Base,Sub 类中的两个属性baseName 分配存储空间,但是不初始化;

 

注意:属性的初始化时放在构造器中,按照代码顺序执行的。

 

5. new Sub会调用Sub的无参构造器,而在这个构造器中会隐式调用父类Base的无参构造器;

 

6. 父类Base的构造器中代码本质是

 

public Base()

{

baseName = "base";

callName();

}

 

即父类的属性baseName 的值为base。但为何输出null,骚年别急。

 

7. 因为父类构造器方法是在子类中调用的,即大环境是子类。此时,调用的方法callName()当然是指子类的方法。而这个方法打印的属性baseName当然也是子类的。那现在子类的属性baseName的值是多少呢?答案是null.因为此时子类Sub的构造器内代码本质是:

 

super();

baseName="sub";

此时baseName="sub"还没执行。

 

因此,最后的值当然是null.

 

 附上代码:

public class A {
    static B b = new B(3);
    B bb = new B(4);

    A() {
        System.out.println("A constructor");
    }

    static {
        System.out.println("A static block");
    }
    {
        System.out.println("A block");
    }
}
public class C extends A {
    static B b = new B(1);
    B bb = new B(2);
    C() {
        System.out.println("C constructor");
    }
    static {
        System.out.println("C static block");
    }
    {
        System.out.println("C block");
    }
    public static void main(String[] args) {
        C c = new C();
    }
}
class B {
    B(int i) {
        System.out.println("B"+i);
    }
}

 

 

posted @ 2015-10-22 22:53  少年啦飞驰  阅读(750)  评论(1编辑  收藏  举报