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

(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);
}
}

java初始化构造函数调用顺序的更多相关文章

  1. C# 构造函数调用顺序

    了解C#的一个类的加载过程,对于语言机制的理解和写出高效的语言很有帮助,这里简单介绍一下类的实例的构造函数调用过程.C#类的实例的构造过程是,先为实例的数据字段分配内存,并对所有字段按字节置零(0或者 ...

  2. JAVA & .NET创建对象构造函数调用顺序

    JAVA 定义Person类 package models; ​ public class Person { public Person() { System.out.println("pe ...

  3. java初始化块执行顺序

    java中初始化块的执行顺序在构造器之前,多个初始化块之间定义在前的先执行.如下: public class InitialBlockTest { // The first one { System. ...

  4. C++派生类构造函数调用顺序(详解)

    我们来看下面一段代码: class B1 { public: B1(int i) {cout<<"constructing B1 "<<i<<e ...

  5. java abstract构造函数调用

    构造函数是对象的基本,没有构造函数就没有对象.如果在父类中(这里就是你的抽象类)中显示的写了有参数的构造函数,在子类继承是就必须写一个构造函数来调用父类的构造函数 public abstract cl ...

  6. java 初始化顺序

    java 变量类型如下: 实例变量: 类变量: 初始化途经如下: 实例变量 --声明时,初始化: --非静态初始化块内,初始化: --构造函数内,初始化: 实例1: public class bean ...

  7. Java初始化顺序

    package com.helei.init; class Log { public static String fatherStaticString(){System.out.println(&qu ...

  8. Java 初始化字段方式和顺序

    Java 初始化字段方式和顺序: 类加载时直接初始化静态字段; 类加载时调用静态方法初始化静态字段; 实例化对象时,在调用构造函数之前代码块中初始化字段; 实例化对象时,在调用构造函数之时初始化字段; ...

  9. C++ 全局构造函数调用的顺序

    C++的全局类和静态类的构造函数是在main函数之前调用的.但是,不同的类的构造函数以什么顺序调用呢? 对于g++编译器来说,这个顺序是由链接时,文件顺序决定的. 我们用一个例子来说明这一点. 我们有 ...

随机推荐

  1. file_get_contents()获取https出现这个错误Unable to find the wrapper “https” – did

    file_get_contents()获取https出现这个错误Unable to find the wrapper “https” – did 解决办法 ,如果你是用的服务器,可以参考这个办法,修改 ...

  2. ubuntu-15.04-server-i386.iso 安装 Oracle 11gR2 数据库

    特点: 需要重新安装老版本的 libaio1_0.3.109-2ubuntu?_i386.deb.默认的libaio库有问题,和其默认libaio的编译方式有关! 默认的gcc 4.9 需要使用 -W ...

  3. Spark源码系列(九)Spark SQL初体验之解析过程详解

    好久没更新博客了,之前学了一些R语言和机器学习的内容,做了一些笔记,之后也会放到博客上面来给大家共享.一个月前就打算更新Spark Sql的内容了,因为一些别的事情耽误了,今天就简单写点,Spark1 ...

  4. Java Web dev搭建经验总结

    摘要: 原创出处:www.bysocket.com 泥瓦匠BYSocket 希望转载,保留摘要,谢谢! 回馈分析法使我看到,我对专业技术人员,不管是工程师.会计师还是市场研究人员,都容易从直觉上去理解 ...

  5. SecureCRT使用

    SecureCRT可以说是linux远程终端的代名词,关于它的一些技巧必须掌握,,, 1.解决中文乱码 登陆主机,运行locale命令,确定语言选项LANG是否为 zh_CN.gb2312 或者 en ...

  6. Qt snippet — 打开文件&保存文件

    打开文件: void Notepad::on_actionOpen_triggered() { QString fileName = QFileDialog::getOpenFileName(this ...

  7. 组合模式及C++实现

    组合模式 组合模式,是为了解决整体和部分的一致对待的问题而产生的,要求这个整体与部分有一致的操作或行为.部分和整体都继承与一个公共的抽象类,这样,外部使用它们时是一致的,不用管是整体还是部分,使用一个 ...

  8. LuaInterface简介

    Lua是一种很好的扩展性语言,Lua解释器被设计成一个很容易嵌入到宿主程序的库.LuaInterface则用于实现Lua和CLR的混合编程. (一)Lua from the CLR 测试环境:在VS2 ...

  9. DDD:四色原型中Role的 “六” 种实现方式

    背景 一个实体在不同的上下文中具备不同的职责,如:产品在“生产完成上下文”中具备的一些职责,在“质检相关上下文”中具备另外一些职责.四色原型.DIC和“UML事物模式”在不同的维度阐述了这一情况,在代 ...

  10. 数据可视化(3)--Google Charts

    Google Chart API 是谷歌提供的一项动态生成图表的服务.你可以随时自定义图表,以适应网站的外观和感觉.图表使用HTML5/SVG技术提供给iPhone手机, iPad和Android的跨 ...