一、java对象初始化过程

  第一步,加载该类,一个java对象在初始化前会进行类加载,在JVM中生成Class对象。加载一个类会进行如下操作,下面给出递归描述。(关于Class对象详见反射 点击这里)

    如果该类有父类,则先加载其父类。    

    i 初始化该类静态成员

    ii 执行该类静态代码块

  第二步,创建对象,如果该类有父类,则创建对象时会先创建其父类的对象,外层包裹子类的属性和方法,然后返回子类的引用,下面给出递归描述。

    如果该类有父类,先创建父类的对象。

    i 初始化该类普通成员。  

    ii 执行普通代码块。

    iii 调用该类构造方法。

二、案例测试

  该类对象作为成员变量

public class Info{
public Info(String s) {
System.out.println(s);
}
}

  父类

public class Parent {

    public static Info info = new Info("Parent static member");      //静态成员

    public Info info2 = new Info("Parent common member");            //普通成员

    static {                                                         //静态代码块
System.out.println("parent static block");
} { //普通代码块
System.out.println("parent common block");
} public Parent() { //父类构造方法
System.out.println("Parent.Parent()");
}
}

  子类

public class Child extends Parent{

    public static Info info = new Info("Child static member");       //静态成员

    public Info info2 = new Info("Child common member");             //普通成员

    static {                                                         //静态代码块
System.out.println("Child static block");
} { //普通代码块
System.out.println("Child common block");
} public Child() { //子类构造方法
System.out.println("Child.Child()");
}
}

 下面测试类的加载过程,我们不创建对象,而是直接加载类,并且是加载子类

public class InitObjectTest{
public static void main(String[] args) {
try{
//Class.forName("Parent");
Class.forName("Child");
}catch(Exception e){ }
//System.out.println("=============== now , we create an Object below ===========");
//new Parent();
}
}

测试结果:

测试结果符合上面所写的加载类的规则,先初始化父类静态成员,再执行父类静态块,然后初始化子类静态成员,最后执行子类静态块。我们可以看到静态成员确实在类加载时初始化。

注意:类的加载只进行一次,之后创建对象将不再进行类加载,这也是为什么静态代码块只执行一次的原因。

下面,将父类加载与创建父类对象分开,观察测试结果

public class InitObjectTest{
public static void main(String[] args) {
try{
//Class.forName("Parent");
Class.forName("Parent");
}catch(Exception e){ }
System.out.println("=============== now , we create an Object below ===========");
new Parent();
}
}

测试结果:

测试结果符合上面的规则,我们先显示的加载了Parent类,所以后面在new Parent()时就没有再加载类了。在创建对象时,先初始化普通成员,再执行普通代码块,最后调用构造方法。

下面加上子类进行测试。

public class InitObjectTest{
public static void main(String[] args) {
try{
//Class.forName("Parent");
//Class.forName("Parent");
}catch(Exception e){ }
System.out.println("=============== now , we create an Object below ===========");
new Child();
}
}

测试结果:

当我们没有显示的加载类时,new对象时,会自动加载类。而输出的前四行就是,加载类的反应。后面的六行是创建对象的反应,先初始父类的普通成员,再执行父类的普通代码块,然后调用父类构造方法,然后进行子类的类似操作。完全符合上面描述的创建过程。

下面测试,先加载父类,然后直接创建子类对象。

public class InitObjectTest{
public static void main(String[] args) {
try{
//Class.forName("Parent");
Class.forName("Parent");
}catch(Exception e){ }
System.out.println("=============== now , we create an Object below ===========");
new Child();
}
}

测试结果:

首先就加载了父类,在创建子类对象时需要加载子类,加载子类时,需要加载父类,而父类在之前就已经加载过了,所以这里并没有再次加载。

三、总结

  到此,静态成员、静态代码块、普通成员、普通代码块、构造方法以及父类的这些模块之间的执行时序就讲完了。分成加载和创建两个步骤来看,十分清晰,每个步骤中又涉及父类的加载,这是一个递归的过程。成员的初始化在代码块的执行之前,因为代码块可能会操作成员。代码块常常用于初始化成员。

  本文个人编写,水平有限,如有错误,恳请指出,欢迎讨论分享

java 对象的初始化流程(静态成员、静态代码块、普通代码块、构造方法)的更多相关文章

  1. java 对象的初始化过程

    PersonDemo p=new PersonDemo("lisi",20);这句话都做了什么事情? 因为new用到了PersonDemo.class,所以会先找到PersonDe ...

  2. Java对象的初始化顺序

    new一个对象时,该对象的初始化顺序如下 : 父类中的静态成员变量 父类中的静态代码块 子类中的静态成员变量 子类中的静态代码块 父类中的非静态变量 父类中的非静态代码块 父类构造函数 子类中的非静态 ...

  3. Java类的初始化顺序 (静态变量、静态初始化块、变量、初始...

    很有意思的一篇文章 1.没有继承 静态变量->静态初始化块->变量->变量初始化块->构造方法 2.有继承的情况 父类静态变量->父类静态初始化块->子类静态变量- ...

  4. java对象的初始化过程和创建对象的几种方式

    1.加载父类,加载父类的静态属性和静态代码块 2.加载子类,加载子类的静态属性和静态代码块 3.初始化父类中的非静态属性并赋初值,执行父类非静态代码块,执行父类构造. 4.初始化子类中的非静态属性并赋 ...

  5. Java对象延迟初始化的实现

    一.什么是延迟初始化? 在Java多线程程序中,有时候需要采用延迟初始化来降低初始化类和创建对象的开销. 延迟初始化实际上就是:当我们要进行一些高开销的对象初始化操作时,只有在使用这些对象时才进行初始 ...

  6. JAVA对象的初始化过程

    出处:http://blog.csdn.net/andrew323/article/details/4665379 下面我们通过两个例题来说明对象的实例化过程. 例1:   编译并运行该程序会有以下输 ...

  7. Java对象的初始化

    昨天写的代码被殷老师诟病了,因为太「丑陋」. 原来我的代码结构是这样的: public class ColorRocognizer { ..... public static void main(St ...

  8. java中类的初始化和对象的初始化

    静态的属于全局静态区,这个部分独立存在,不管是成员还是块,都是静态的,大家地位相等,先到先得. 然后是成员初始化,这个部分在类的构造函数前初始化,因为编译器(或者设计者)可能认为构造函数调用了这个成员 ...

  9. 解析Java类和对象的初始化过程

    类的初始化和对象初始化是 JVM 管理的类型生命周期中非常重要的两个环节,Google 了一遍网络,有关类装载机制的文章倒是不少,然而类初始化和对象初始化的文章并不多,特别是从字节码和 JVM 层次来 ...

随机推荐

  1. ZT 七大寡头

    网易评论人才辈出啊!!!看下面   http://comment.news.163.com/news_guoji2_bbs/9GRIIJA90001121M.html 关注 关注他的微博yftyfm ...

  2. Python 冒泡排序法分析

    冒泡排序法 def maopao(): array = [2,1,3,6,5,4] #确定一组需要排序的数值列表 for i in range(len(array)-1): #大循环次数=列表长度,但 ...

  3. Oracle 查找带有CLOB字段的所有表

    查找带有CLOB字段的以HEHE开头的所有表 select t.column_name ,DATA_TYPE,TABLE_NAMEfrom user_tab_columns twhere t.TABL ...

  4. composer的基本运用

    Composer -- PHP依赖管理的新时代 一.简介 说到composer,绝大多数的开发人员都会用到.composer是一个什么工具呢? composer 是 PHP 用来管理依赖(depend ...

  5. python查看微信消息撤回

    准备环境 python语言环境 python解释器-pycharm itchat介绍 itchat是一个开源的微信个人号接口,通过itchat可以实现微信(好友或微信群)的信息处理,包括文本.图片.小 ...

  6. Address already in use

    1.错误描述 2011-7-20 11:05:18 org.apache.catalina.core.StandardServer await严重: StandardServer.await: cre ...

  7. usb入门学习

    1.学习资源: usb org.http://www.beyondlogic.org/usbnutshell/usb3.shtml http://wenku.baidu.com/view/028231 ...

  8. UCOS阅读问题累积

    1.#ifdef __cplusplus   extern "C" {  #endif 作用: 一般用于将C++代码以标准C形式输出(即以C的形式被调用),这是因为C++虽然常被认 ...

  9. oracle 的replace()

    1.查询所有员工的姓名,如果包含字母s,则用S替换. 2.查询所有员工姓名的前三个字符.

  10. Mybatis 原始dao CRUD方法

    用到的相关jar包及所用版本如下: 其中的Mybatis可以到github.com的网站下载 <project xmlns="http://maven.apache.org/POM/4 ...