Java的初始化执行顺序(父类static变量->子类static变量->父类成员变量->父类构造器->成员变量->构造器->main函数)
1. 引言
了解Java初始化的顺序,有助于理解Java的初始化机制和内存机制。
顺序:父类static变量->子类static变量->父类成员变量->父类构造器->成员变量->构造器->main函数(说明:static变量包括static变量和static代码块,按位置顺序执行)
2. 样例
2.1 无继承的类的初始化顺序
public class TestClass {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("Creating new Cupboard() in main");
new Cupboard();
System.out.println("Creating new Cupboard() in main");
new Cupboard();
t2.f2(1);
t3.f3(1);
}
static Table t2 = new Table();
static Cupboard t3 = new Cupboard();
}
// : StaticInitialization.java
// Specifying initial values in a
// class definition.
class Bowl {
Bowl(int marker) {
System.out.println("Bowl(" + marker + ")");
}
void f(int marker) {
System.out.println("f(" + marker + ")");
}
}
class Table {
static Bowl b1 = new Bowl(1);
static{
System.out.println("Table() static 1");
}
Table() {
System.out.println("Table()");
b2.f(1);
}
void f2(int marker) {
System.out.println("f2(" + marker + ")");
}
Bowl b10 = new Bowl(10);
{
System.out.println("Table() non-static");
}
Bowl b11 = new Bowl(11);
static Bowl b2 = new Bowl(2);
static{
System.out.println("Table() static 2");
}
}
class Cupboard {
Bowl b3 = new Bowl(3);
static Bowl b4 = new Bowl(4);
Cupboard() {
System.out.println("Cupboard()");
b4.f(2);
}
void f3(int marker) {
System.out.println("f3(" + marker + ")");
}
static Bowl b5 = new Bowl(5);
}
输出的结果如下:
Bowl(1)
Table() static 1
Bowl(2)
Table() static 2
Bowl(10)
Table() non-static
Bowl(11)
Table()
f(1)
Bowl(4)
Bowl(5)
Bowl(3)
Cupboard()
f(2)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f(2)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f(2)
f2(1)
f3(1)
2.2 有继承的类的初始化顺序
//: Beetle.java
// The full process of initialization. class Insect {
int i = 9;
int j;
Insect() {
prt("i = " + i + ", j = " + j);
j = 39;
}
static{
System.out.println("Insert static block0");
} static int x1 =
prt("static Insect.x1 initialized");
static int prt(String s) {
System.out.println(s);
return 47;
}
static{
System.out.println("Insert static block1");
}
} public class Beetle extends Insect {
int k = prt("Beetle.k initialized");
Beetle() {
prt("k = " + k);
prt("j = " + j);
}
static int x2 =
prt("static Beetle.x2 initialized");
static int prt(String s) {
System.out.println(s);
return 63;
}
public static void main(String[] args) {
prt("Beetle constructor"); //flag 1
Beetle b = new Beetle(); //flag 2
}
} ///:~
输出的结果如下:
Insert static block0
static Insect.x1 initialized
Insert static block1
static Beetle.x2 initialized
Beetle constructor
i = 9, j = 0
Beetle.k initialized
k = 63
j = 39 //如果只把flag 1 那条语句注释掉,输出内容如下:
Insert static block0
static Insect.x1 initialized
Insert static block1
static Beetle.x2 initialized
i = 9, j = 0
Beetle.k initialized
k = 63
j = 39 //如果只把flag 2 那条语句注释掉,输出内容如下:
Insert static block0
static Insect.x1 initialized
Insert static block1
static Beetle.x2 initialized
Beetle constructor
3. 总结
只要按照这个顺序:父类static变量->子类static变量->父类成员变量->父类构造器->成员变量->构造器->main函数(说明:static变量包括static变量和static代码块,按位置顺序执行), 去推导初始化执行顺序就能得到正确的执行答案数据。
注意点:
1.若仅仅执行static方法,则只会执行该类及其父类的所有静态变量,而且静态变量只会被执行一次
2.当对象被new出来时,才会开始初始化该类及其父类的所有变量,按照以上的说的顺序执行
3.成员或者静态static变量若申明时不赋值,会被初始化相应类型的默认值,例如int是0,String是null等
4.可以用debug模式直接断点调试,跟着走一遍,就能看到代码是怎么初始化变量的(当然,自己先演练一遍,效果更好)
4.参考
Thinking in Java P113, P158
Java的初始化执行顺序(父类static变量->子类static变量->父类成员变量->父类构造器->成员变量->构造器->main函数)的更多相关文章
- Java子类和父类的初始化执行顺序
要明白子类和父类的初始化执行顺序,只需要知晓以下三点,就不会再弄错了. 1.创建子类对象时,子类和父类的静态块和构造方法的执行顺序为:父类静态块->子类静态块->父类构造器->子类构 ...
- 关于java中构造方法、实例初始化、静态初始化执行顺序
在Java笔试中,构造方法.实例初始化.静态初始化执行顺序,是一个经常被考察的知识点. 像下面的这道题(刚刚刷题做到,虽然做对了,但是还是想整理一下) 运行下面的代码,输出的结果是... class ...
- Java程序初始化的顺序
Java程序初始化的顺序 java程序初始化工作可以在许多不同的代码块中来完成(例如:静态代码块.构造函数等),他们执行的顺序如下: 父类静态变量 父类静态代码块 子类静态变量 子类静态代码块 父类非 ...
- 八、 Java程序初始化的顺序(一)
今天在写构造器方法的时候,遇到了一个小问题,由这个问题引发了一连串的思考,在一个Java类中变量与类的初始化执行顺序是什么样的呢?## 发现问题 class Student{ private Stri ...
- java代码块执行顺序
父类 public class Father { public Father() { System.out.println("父类构造PUBLIC father"); } stat ...
- C#类、静态类、静态变量,初始化执行顺序
执行顺序: 类的静态变量 ↓ 类的静态构造函数 ↓ 类的普通变量 ↓ 基类的静态变量 ↓ 基类的静态构造函数 ↓ 基类的普通变量 ↓ 基类的构造函数 ↓ 类的构造函数
- 《Java程序员面试笔试宝典》之Java程序初始化的顺序是怎样的
在Java语言中,当实例化对象时,对象所在类的所有成员变量首先要进行初始化,只有当所有类成员完成初始化后,才会调用对象所在类的构造函数创建对象. Java程序的初始化一般遵循以下三个原则(以下三原则优 ...
- 《Java程序猿面试笔试宝典》之Java程序初始化的顺序是如何的
在Java语言中.当实例化对象时.对象所在类的全部成员变量首先要进行初始化,仅仅有当全部类成员完毕初始化后,才会调用对象所在类的构造函数创建对象. Java程序的初始化一般遵循以下三个原则(以下 ...
- 九、 Java程序初始化的顺序(二)
之前的一篇博客里我写了关于在一个类中的程序初始化顺序,但是在Java的面向对象里,类之间还存在着继承的关系.所以关于程序的初始化顺序,我们可以再细划分为:父类静态变量,父类的静态代码块,父类构造器,父 ...
随机推荐
- 多线程状态下调用SimpleDateFormat.format()抛出 ArrayIndexOutOfBoundsException 异常
本来想在类的顶部设置一个 静态的SimpleDateFormat常量 public final static DateFormat dateFormatGMT = new SimpleDateForm ...
- django---APIView源码分析
django---APIView源码分析 前言:APIView基于View 看这部分内容一定要懂django-CBV里的内容 在django-CBV源码分析中,我们是分析的from django.vi ...
- random模块(十九)
1 ).random() 返回0<=n<1之间的随机实数n: 2 ).choice(seq) 从序列seq中返回随机的元素: 3 ).getrandbits(n) 以长整型形式返回n个随机 ...
- java.lang.OutOfMemoryError: unable to create new native thread 居然是MQ问题
问题: 开发环境,之前一直正常,某天突然用tomcat启动项目后时不时报如下错误: java.lang.OutOfMemoryError: unable to create new native th ...
- python---tornado初识(2)实现登录和发布文章
# coding:utf8 # __author: Administrator # date: 2018/3/6 0006 # /usr/bin/env python import tornado.i ...
- JAVA-大白话探索JVM-类加载过程(二)
首先我们知道JVM是什么以及类加载器的作用 不清楚的可以看看JAVA-大白话探索JVM-类加载器(一) 现在我们来摸索下类的加载过程 首先,我们将类加载过程分为三步走 装载 链接 初始化 其中 链接 ...
- Study 7 —— CSS美化背景和边框
图片透明度属性:opacity 背景图片重复属性:background-repeat背景图片位置属性:background-position background-postion:横坐标 纵坐标; b ...
- .NET面试题系列(十一)WinDbg、Perfmon
WinDbg 资料 https://www.cnblogs.com/sheng-jie/p/9503650.html https://www.cnblogs.com/yudongdong/p/9701 ...
- 10 SpringBoot全面接管SpringMVC
Spring Boot官方文档描述 If you want to keep Spring Boot MVC features and you want to add additional MVC co ...
- Idea下安装Lombok插件
参照:http://www.cnblogs.com/holten/p/5729226.html https://yq.aliyun.com/articles/59972 lombok是一个可以通过简单 ...