一、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. lua-excel助手

    excel是我们工作及生活当中不可或缺的东西,好吧,我是一个游戏程序员,数值哥哥肯定会给我些表格的.回归正题,为什么需要做这个封装? 为什么需要这个项目,因为我们需要使用程序进行自动化操作 VBA我们 ...

  2. soapui使用。简单测试+测试套+负载测试。

    http://www.cnblogs.com/zerotest/tag/soapui/

  3. February 14 2017 Week 7 Tuesday

    Love lives in cottages as well as in courts. 爱情无贵贱,贫富皆有之. Many people, especially boys, complain tha ...

  4. Go语言(三)反射机制

    package main import( "fmt" "reflect" ) func main(){ // iterate through the attri ...

  5. 奇葩拿shell + 提权wind08r2奇葩拿shell + 提权wind08r2戏

    0x01 小隐拿站篇 某省还是市级还是县级的空防部 先来刺探目录,拿起御剑, 啪啪啪  (鼓掌)后台出来了   试试弱口令 擦  需要管理员验证码,这个咋玩????这个注入都不用找了,就算注射出账号密 ...

  6. web API之post参数传递

    最近公司开发一个新产品,前端用的vue+element,后端用的.net core ,刚开始接触这块,接口写完后在调用接口时总出现问题,尤其是post传递参数时,很多时候都获取不到参数,没办法接口都要 ...

  7. 使用redux开发的简单步骤

    一.安装redux包 npm install redux --save 二.根据APP数据结构或者后台请求的数据结构拟定state的大致结构. 可以把state写成一个对象字面量,放在reducer文 ...

  8. Mutual Training for Wannafly Union #2

    codeforces 298A. Snow Footprints 分类讨论三种情况: ①..RRRRRR…  ②..LLLLLLL… ③..RRRLLLL.. //AC by lwq: #includ ...

  9. 鲁宾斯坦说:"思维是在概括中完成的。"

    鲁宾斯坦说:"思维是在概括中完成的."

  10. 理解JavaScript的this对象

    1.概述 this对象是在运行时基于函数的执行环境绑定的,this总是返回一个对象,简单说,就是返回属性或方法"当前"所在的对象.在全局函数中,this等于window,而当函数作 ...