当创建一个对象时,各种成员变量及构造方法的初始化或调用顺序是怎样的呢?

(1).如果类尚未加载,则先初始化静态成员变量和静态代码块,再初始化成员变量,最后调用相应的构造方法;

(2).如果类已经加载过了,则静态成员变量已经初始过了,静态代码块也已执行,这时只需初始化成员变量,再调用构造方法就可以了;

(3).如果类还有父类,则按(1)或(2)的顺序先初始化父类,再初始化子类。

下面以例子详细说明。

包human中定义了四个类,分别为Person、Student、DustMan、TestMain;其中,Student是Person的子类。

Person类的代码如下:

package human;

public class Person {
String name;
String gender; //test:成员变量的初始化是否在构造方法调用之前 2017.11.01
public Person() {
System.out.println("Person constructor:Person()");
} DustMan dustTest = new DustMan(); static {
System.out.println("Person:initialization of static code block");
}
static String citizenship = "Chinese"; //test:静态成员变量与静态代码块的初始化顺序 2017.11.01 //test:子类用super显式调用父类构造方法时,各变量及构造方法初始化或调用顺序 2017.11.01
public Person(String n, String g) {
this.name = n;
this.gender = g;
System.out.println("Person constructor:Person(n,g)");
}
}

Student类的代码如下:

package human;

public class Student extends Person {
String stuNumber;
int score; static String testIni = "test";
static {
System.out.println("Student:testIni = " + testIni);
}
//test:成员变量的初始化是否在构造方法调用之前 2017.11.01
public Student() {
System.out.println("Student constructor:Student()");
} //test:子类用super显式调用父类构造方法时,各变量及构造方法初始化或调用顺序 2017.11.01
public Student(String n, String g) {
super(n,g);
System.out.println("Student constructor:Student(n,g)");
}
}

DustMan类的代码如下:

package human;

public class DustMan {
public DustMan() {
System.out.println("DustMan constructor");
System.out.println("change value of the static variable citizenship " + "\"" + Person.citizenship + "\"");
Person.citizenship = "US";
System.out.println(" to " + "\"" + Person.citizenship + "\"");
}
}

TestMain类的代码如下:

package human;

public class TestMain {

	public static void main(String[] args) {
Student stuTest = new Student();
Student stuTest2 = new Student("liu","female"); System.out.println("citizenship = " + Person.citizenship);
}

在TestMain类中执行,输出结果如下:

Person:initialization of static code block
Student:testIni = test
DustMan constructor
change value of the static variable citizenship "Chinese"
to "US"
Person constructor:Person()
Student constructor:Student()
DustMan constructor
change value of the static variable citizenship "US"
to "US"
Person constructor:Person(n,g)
Student constructor:Student(n,g)
citizenship = US

下面对输出结果进行分析:

(1).执行第一条语句,创建对象stuTest,Student stuTest = new Student();

<1>.输出的第1行:Person:initialization of static code block

可以看出,虽然创建的是Student类对象,但先加载的是父类,加载时执行Person类的静态代码块,有第一行输出。

<2>.输出的第2行:Student:testIni = test

加载过父类后,并没有接着初始父类的成员变量及调用构造方法,而是接着加载了子类Student,加载时执行Student的静态代码块,有第二行输出。

<3>.输出的第3行:DustMan constructor

Person类和Student类都加载后,开始初始化Person类的成员变量,有一个变量是DustMan类型的,即DustMan dustTest = new DustMan();dustTest的定义虽然在无参构造方法的后面,但根据输出结果看,先初始化的对象dustTest,后调用的构造方法,也就是说成员变量的初始化在构造方法的调用之前

<4>,输出的第4行和第5行:change value of the static variable citizenship "Chinese"

to "US"

可以看出,在Person的构造方法调用之前,静态成员变量citizenship已经被初始为“Chinese”了,在DustMan的构造方法中又被修改为“US”。

<5>.输出的第6行:Person constructor:Person()

Person类的成员变量初始化完成后,接着调用构造方法Person()。

<6>.输出的第7行:Student constructor:Student()

Person类构造方法调用后,接着初始化子类成员变量,并调用构造方法。

(2).第一条语句已经执行完,接着执行第二条语句Student stuTest2 = new Student("liu","female");

<7>.输出的第8行:DustMan constructor

很明显,创建第二个Student对象stuTest2时,父类和子类的静态代码块都没有再执行,直接初始化成员变量。

<8>输出的第9行和第10行:change value of the static variable citizenship "US"

to "US"

citizenship的值由第<4>步改为“US”后就没有发生变化,说明静态成员变量也没有再次初始化为"Chinese"。

<9>.输出的第11行:Person constructor:Person(n,g)

父类的成员变量初始化后,接着调用构造方法,这次调用的不是无参构造方法,而是Person(n,g);Student的构造方法Student(n,g)里用super(n,g)显式的调用了父类的构造方法,说明要调用父类哪个构造方法是由子类的构造方法决定的。

<10>.输出的第12行:Student constructor:Student(n,g)

父类构造方法调用后,接着初始化子类成员变量,并调用子类构造方法。

<11>.输出的第13行:citizenship = US

再次确认citizenship的值没有重新初始化。

(3).在Person的静态代码块中添加一行System.out.println("citizenship = " + citizenship);,如下所示:

	static {
System.out.println("Person:initialization of static code block");
System.out.println("citizenship = " + citizenship);
}
static String citizenship = "Chinese"; //test:静态成员变量与静态代码块的初始化顺序 2017.11.01

出现Cannot reference a field before it is defined的错误,说明静态代码块的执行和静态成员变量的初始化是按定义的顺序执行的。

总结:

(1).首次使用类时,先加载类,加载时初始类的静态成员变量,执行静态代码块;

静态成员变量和静态代码块的顺序按定义的顺序来;

静态成员变量和静态代码块都只在类加载时初始化或执行一次。

(2).如果有父类,则先加载父类,再加载子类。

(3).new一个对象时,父类子类都加载后,先初始化父类的成员变量,再调用父类的构造方法;

调用父类的哪个构造方法要看new时调用的子类的哪个构造方法,看子类的这个构造方法是如何使用super(参数),执行与super的参数一致的父类构造方法。

(4).父类调用过构造方法后,再初始化子类成员变量,再调用子类的构造方法。

Java学习笔记11---静态成员变量、静态代码块、成员变量及构造方法的初始化或调用顺序的更多相关文章

  1. java 对象的初始化流程(静态成员、静态代码块、普通代码块、构造方法)

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

  2. java 子类、父类中静态代码块、字段,非静态代码块、字段以及构造函数的初始化顺序和次数

    一个类中的数据初始化顺序是面试官非常喜欢出的面试题之一,本文用一个实例来介绍java中子类.父类中静态代码块.字段,非静态代码块.字段以及构造函数的执行顺序和次数. 一.包结构

  3. 0013 Java学习笔记-面向对象-static、静态变量、静态方法、静态块、单例类

    static可以修饰哪些成员 成员变量---可以修饰 构造方法---不可以 方法---可以修饰 初始化块---可以修饰 内部类(包括接口.枚举)---可以修饰 总的来说:静态成员不能访问非静态成员 静 ...

  4. java 静态变量 静态代码块 加载顺序问题

    在网上看了一个这样的题目 public class StaticTest { public static void main(String[] args) { staticFunction(); } ...

  5. Android(java)学习笔记188:关于构造代码块,构造函数的一道面试题(华为面试题)

    1.源码是: package text; public class TestStaticCon { public static int a = 0; static { a = 10; System.o ...

  6. Android(java)学习笔记131:关于构造代码块,构造函数的一道面试题(华为面试题)

    1. 代码实例: package text; public class TestStaticCon { public static int a = 0; static { a = 10; System ...

  7. java新手笔记11 类的静态属性、方法(单例)

    1.Person类 package com.yfs.javase; public class Person { String name;//每个对象上分配 与对象绑定 int age; char se ...

  8. Java类的装载过程和静态代码块

    在Java中,类装载器把一个类装入Java虚拟机中,要经过三个步骤来完成:装载.连接和初始化,其中连接又可以分成校验.准备和解析三步,除了解析外,其它步骤是严格按照顺序完成的,各个步骤的主要工作如下: ...

  9. Java学习笔记(三)——静态导入,package-info,Fall-through

    [前面的话] 算是真正的放松了好几天时间,没有看任何书,没有任何任务,今天是过完年后的第一天上班时间,我又开始了我的学习之路,感觉还没有老,怎么心态越来越平静了,进入工作状态,就好好努力工作,新的一年 ...

随机推荐

  1. Struts框架的国际化

    本文将通过一个详细的实例来展示Struts框架的国际化,使用的版本号是struts1.1. 案例:在一个页面上有一个下拉框,下拉框中有3个国家的语言选项,各自是"中文简体".&qu ...

  2. hdu4893 Wow! Such Sequence!

    线段树结点上保存一个一般的sum值,再同一时候保存一个fbsum,表示这个结点表示的一段数字若为斐波那契数时的和 当进行3操作时,仅仅用将sum = fbsum就可以 其它操作照常进行,仅仅是单点更新 ...

  3. 做ppt经常使用站点

    推荐一下做PPT经常使用的站点 一.字体 http://font.chinaz.com 二.ppt模板:演界网 三.图标 http://www.easyicon.net/

  4. AOP入门(转)

    本文转自http://www.cnblogs.com/yanbincn/archive/2012/06/01/2530377.html Aspect Oriented Programming  面向切 ...

  5. Tencent社会招聘scrapy爬虫 --- 已经解决

    1.用 scrapy 新建一个 tencent 项目 2.在 items.py 中确定要爬去的内容 # -*- coding: utf- -*- # Define here the models fo ...

  6. 以List为例浅谈C#的学习方法

    前言:关于学习方法的讨论其实是个比较模糊的概念,对于List的介绍的资料其实已经很多了,但是一般是介绍List本身,我打算分享的是,以温故List为例,来获取新知识的这么一个过程.这里的新知识也不是什 ...

  7. Visual Studio中将打开的代码与类文件进行关联

  8. 中文颜色名称与RGB颜色对照表

    中文颜色名称颜色对照表 鸨色 #f7acbc 赤白橡 #deab8a 油色 #817936 绀桔梗 #444693 踯躅色 #ef5b9c 肌色 #fedcbd 伽罗色 #7f7522 花色 #2b4 ...

  9. iOS UICollectionView(转一) XIB+纯代码创建:cell,头脚视图 cell间距

    之前用CollectionViewController只是皮毛,一些iOS从入门到精通的书上也是泛泛而谈.这几天好好的搞了搞苹果的开发文档上CollectionViewController的内容,亲身 ...

  10. http中的get和post(二)

    博客园精华区有篇文章< GET 和 POST 有什么区别?及为什么网上的多数答案都是错的 >,文中和回复多是对以下两个问题进行了深究: 长度限制 Url 是否隐藏数据 在我看来这两者都不是 ...