java 对象的初始化流程(静态成员、静态代码块、普通代码块、构造方法)
一、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 对象的初始化流程(静态成员、静态代码块、普通代码块、构造方法)的更多相关文章
- java 对象的初始化过程
PersonDemo p=new PersonDemo("lisi",20);这句话都做了什么事情? 因为new用到了PersonDemo.class,所以会先找到PersonDe ...
- Java对象的初始化顺序
new一个对象时,该对象的初始化顺序如下 : 父类中的静态成员变量 父类中的静态代码块 子类中的静态成员变量 子类中的静态代码块 父类中的非静态变量 父类中的非静态代码块 父类构造函数 子类中的非静态 ...
- Java类的初始化顺序 (静态变量、静态初始化块、变量、初始...
很有意思的一篇文章 1.没有继承 静态变量->静态初始化块->变量->变量初始化块->构造方法 2.有继承的情况 父类静态变量->父类静态初始化块->子类静态变量- ...
- java对象的初始化过程和创建对象的几种方式
1.加载父类,加载父类的静态属性和静态代码块 2.加载子类,加载子类的静态属性和静态代码块 3.初始化父类中的非静态属性并赋初值,执行父类非静态代码块,执行父类构造. 4.初始化子类中的非静态属性并赋 ...
- Java对象延迟初始化的实现
一.什么是延迟初始化? 在Java多线程程序中,有时候需要采用延迟初始化来降低初始化类和创建对象的开销. 延迟初始化实际上就是:当我们要进行一些高开销的对象初始化操作时,只有在使用这些对象时才进行初始 ...
- JAVA对象的初始化过程
出处:http://blog.csdn.net/andrew323/article/details/4665379 下面我们通过两个例题来说明对象的实例化过程. 例1: 编译并运行该程序会有以下输 ...
- Java对象的初始化
昨天写的代码被殷老师诟病了,因为太「丑陋」. 原来我的代码结构是这样的: public class ColorRocognizer { ..... public static void main(St ...
- java中类的初始化和对象的初始化
静态的属于全局静态区,这个部分独立存在,不管是成员还是块,都是静态的,大家地位相等,先到先得. 然后是成员初始化,这个部分在类的构造函数前初始化,因为编译器(或者设计者)可能认为构造函数调用了这个成员 ...
- 解析Java类和对象的初始化过程
类的初始化和对象初始化是 JVM 管理的类型生命周期中非常重要的两个环节,Google 了一遍网络,有关类装载机制的文章倒是不少,然而类初始化和对象初始化的文章并不多,特别是从字节码和 JVM 层次来 ...
随机推荐
- php简单的数组递归
参照 http://www.oschina.net/code/snippet_105637_11401 的例子 $arr = array('aa' => array('bb' => ...
- yii2.0 Activeform表单部分组件使用方法 [ 2.0 版本 ]
文本框:textInput(); 密码框:passwordInput(); 单选框:radio(),radioList(); 复选框:checkbox(),checkboxList(); 下拉框:dr ...
- C#中的"?"和"??"
摘自:http://www.cnblogs.com/zxjyuan/archive/2009/10/27/1590795.html 如果你看到C#中的“?”问号脑袋里便充满问号,那么这个贴子便是为你而 ...
- js 联动实现日期选择,一般用作生日
实现目标:年月日三个select 输入框,以及一个hidden的input,通过js获取input的值,如果有值切是日期格式,年月日select为input中的时间.否则为空.年默认区间段为1900年 ...
- BIND简易教程(1):安装及基本配置
首先,为什么说是简易教程呢?因为BIND的功能实在太多,全写出来的话要连载好久,我觉得我没有那么多精力去写:而我了解的仅仅是有限的一点点,不敢造次.百度上的文章也是一抓一大把呐!所以,教点基本使用方法 ...
- PAT——1001. 害死人不偿命的(3n+1)猜想
卡拉兹(Callatz)猜想: 对任何一个自然数n,如果它是偶数,那么把它砍掉一半:如果它是奇数,那么把(3n+1)砍掉一半.这样一直反复砍下去,最后一定在某一步得到n=1.卡拉兹在1950年的世界数 ...
- C51 单片机的中断号以及中断向量
1.外部中断0. 1:分别由引脚/INT0./INT1的电平信号引起. 2.定时/计数器0.1:分别由T0. T1的溢出引起. 3.串行口发送.接收:发送完一个字节或接收到一个字节引起. 上述共5个中 ...
- NopCommerce学习(2) EntityFramework
NopCommerce-EntityFramework开发:主要是Controller-Service-Repository的开发方式 操作数据库,主要对象是BaseEntity,IDbContext ...
- 集合Gk表示这样一堆数字,该集合内的数字有k个1
问题描述 集合Gk表示这样一堆数字,该集合内的数字有k个1.比如,G1 = { 1, 10, 100, 1000, ...} G2 = {11, 110, 1110 }, ... , Gk { ... ...
- MySQL必知必会 读书笔记一:简介
了解数据库 数据库(database) 数据库(database) 保存有组织的数据的容器(通常是一个文 件或一组文件). 数据库软件应称为DBMS(数据库管理系统).数据库是通过DBMS创建和操纵的 ...