Java学习笔记11---静态成员变量、静态代码块、成员变量及构造方法的初始化或调用顺序
当创建一个对象时,各种成员变量及构造方法的初始化或调用顺序是怎样的呢?
(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---静态成员变量、静态代码块、成员变量及构造方法的初始化或调用顺序的更多相关文章
- java 对象的初始化流程(静态成员、静态代码块、普通代码块、构造方法)
一.java对象初始化过程 第一步,加载该类,一个java对象在初始化前会进行类加载,在JVM中生成Class对象.加载一个类会进行如下操作,下面给出递归描述.(关于Class对象详见反射 点击这里) ...
- java 子类、父类中静态代码块、字段,非静态代码块、字段以及构造函数的初始化顺序和次数
一个类中的数据初始化顺序是面试官非常喜欢出的面试题之一,本文用一个实例来介绍java中子类.父类中静态代码块.字段,非静态代码块.字段以及构造函数的执行顺序和次数. 一.包结构
- 0013 Java学习笔记-面向对象-static、静态变量、静态方法、静态块、单例类
static可以修饰哪些成员 成员变量---可以修饰 构造方法---不可以 方法---可以修饰 初始化块---可以修饰 内部类(包括接口.枚举)---可以修饰 总的来说:静态成员不能访问非静态成员 静 ...
- java 静态变量 静态代码块 加载顺序问题
在网上看了一个这样的题目 public class StaticTest { public static void main(String[] args) { staticFunction(); } ...
- Android(java)学习笔记188:关于构造代码块,构造函数的一道面试题(华为面试题)
1.源码是: package text; public class TestStaticCon { public static int a = 0; static { a = 10; System.o ...
- Android(java)学习笔记131:关于构造代码块,构造函数的一道面试题(华为面试题)
1. 代码实例: package text; public class TestStaticCon { public static int a = 0; static { a = 10; System ...
- java新手笔记11 类的静态属性、方法(单例)
1.Person类 package com.yfs.javase; public class Person { String name;//每个对象上分配 与对象绑定 int age; char se ...
- Java类的装载过程和静态代码块
在Java中,类装载器把一个类装入Java虚拟机中,要经过三个步骤来完成:装载.连接和初始化,其中连接又可以分成校验.准备和解析三步,除了解析外,其它步骤是严格按照顺序完成的,各个步骤的主要工作如下: ...
- Java学习笔记(三)——静态导入,package-info,Fall-through
[前面的话] 算是真正的放松了好几天时间,没有看任何书,没有任何任务,今天是过完年后的第一天上班时间,我又开始了我的学习之路,感觉还没有老,怎么心态越来越平静了,进入工作状态,就好好努力工作,新的一年 ...
随机推荐
- UICollectionView具体解释
初始化部分: UICollectionViewFlowLayout *flowLayout= [[UICollectionViewFlowLayout alloc]init]; self.myColl ...
- 【最短路】 ZOJ 1544 Currency Exchange 推断负圈
给出 N 种货币 M 条兑换关系 開始时全部的货币S 和有X 块钱 接下来M条关系 A B W1 W2 W3 W4 表示 A->B 所需的手续费为W2块钱 汇率为W1 B->A 所需的手 ...
- SharePoint 2013 引发类型为“System.ArgumentException”的异常。 參数名: encodedValue
SharePoint 2013 引发类型为"System.ArgumentException"的异常. 參数名: encodedValue 具体错误信息 说明: 运行当前 Web ...
- ShuffleNet总结
在2017年末,Face++发了一篇论文ShuffleNet: An Extremely Efficient Convolutional Neural Network for Mobile Devic ...
- 支持国内版Office 365的PowerShell模块现已发布
作者:陈希章 发表于2017年5月12日 上一篇文章我详细介绍了如何在PowerShell中访问到Office 365的Graph API,在文章结尾处我留了一个问题,希望有朋友可以根据那个思路,尝试 ...
- .NET Core容器化之多容器应用部署@Docker-Compose
1.引言 紧接上篇.NET Core容器化@Docker,这一节我们先来介绍如何使用Nginx来完成.NET Core应用的反向代理,然后再介绍多容器应用的部署问题. 2. Why Need Ngin ...
- ABP 教程文档 1-1 手把手引进门之 ASP.NET Core & Entity Framework Core(官方教程翻译版 版本3.2.5)
本文是ABP官方文档翻译版,翻译基于 3.2.5 版本 官方文档分四部分 一. 教程文档 二.ABP 框架 三.zero 模块 四.其他(中文翻译资源) 本篇是第一部分的第一篇. 第一部分分三篇 1- ...
- linux应用态下的时间
1.时间值 1.1 日历时间(UTC) 该值是自1 9 7 0年1月1日0 0 : 0 0 : 0 0以来国际标准时间( U T C)所经过的秒数累计值(早期的手册称 U T C为格林尼治标准时间) ...
- Linux服务器配置(一)
Linux服务器配置(一) jdk,tomcat,nginx记录 最近公司买了三台服务器System x3650 M5用来跑公司的项目.现,记录一下真机部署与后期维护历程~ 因为系统是服务器买来就装好 ...
- Intellijidea建javaWeb以及Servlet简单实现
一.创建并设置javaweb工程1.创建javaweb工程File --> New --> Project... 点击Project后出现如下界面,选择Java Enterprise,选中 ...