一、java对象初始化顺序
java对象初始化的执行顺序为:静态语句块>静态变量初始化>实例语句块/成员变量初始化>构造方法,实例语句块与成员变量初始化的相对执行顺序取决于定义的先后顺序
二、非继承关系中的初始化顺序
1.实例
代码如下(示例):
package com.j2se;
public class InitialOrderWithoutExtend {
static SampleClass sam = new SampleClass("静态成员sam初始化");
SampleClass sam1 = new SampleClass("普通成员sam1初始化");
static {
System.out.println("static块执行");
if (sam == null)
System.out.println("sam is null");
sam = new SampleClass("静态块内初始化sam成员变量");
}
SampleClass sam2 = new SampleClass("普通成员sam2初始化");
InitialOrderWithoutExtend() {
System.out.println("InitialOrderWithoutExtend默认构造函数被调用");
}
public static void main(String[] args) {
// 创建第1个主类对象
System.out.println("第1个主类对象:");
InitialOrderWithoutExtend ts = new InitialOrderWithoutExtend();
// 创建第2个主类对象
System.out.println("第2个主类对象:");
InitialOrderWithoutExtend ts2 = new InitialOrderWithoutExtend();
// 查看两个主类对象的静态成员:
System.out.println("2个主类对象的静态对象:");
System.out.println("第1个主类对象, 静态成员sam.s: " + ts.sam);
System.out.println("第2个主类对象, 静态成员sam.s: " + ts2.sam);
}
}
class SampleClass {
// SampleClass 不能包含任何主类InitialOrderWithoutExtend的成员变量
// 否则导致循环引用,循环初始化,调用栈深度过大
// 抛出 StackOverFlow 异常
// static InitialOrderWithoutExtend iniClass1 = new InitialOrderWithoutExtend("静态成员iniClass1初始化");
// InitialOrderWithoutExtend iniClass2 = new InitialOrderWithoutExtend("普通成员成员iniClass2初始化");
String s;
SampleClass(String s) {
this.s = s;
System.out.println(s);
}
SampleClass() {
System.out.println("SampleClass默认构造函数被调用");
}
@Override
public String toString() {
return this.s;
}
}
输出结果:
静态成员sam初始化
static块执行
静态块内初始化sam成员变量
第1个主类对象:
普通成员sam1初始化
普通成员sam2初始化
InitialOrderWithoutExtend默认构造函数被调用
第2个主类对象:
普通成员sam1初始化
普通成员sam2初始化
InitialOrderWithoutExtend默认构造函数被调用
2个主类对象的静态对象:
第1个主类对象, 静态成员sam.s: 静态块内初始化sam成员变量
第2个主类对象, 静态成员sam.s: 静态块内初始化sam成员变量
由输出结果可知,执行顺序为:
- static静态代码块和静态成员
- 普通成员
- 构造函数执行
三、继承关系中的初始化顺序
1.实例
代码如下(示例):
package com.j2se;
public class InitialOrderWithExtend {
public static void main(String[] args) {
Father ts = new Son();
}
}
class Father {
{
System.out.println("父类 非静态块 1 执行");
}
static {
System.out.println("父类 static块 1 执行");
}
static Sample staticSam1 = new Sample("父类 静态成员 staticSam1 初始化");
Sample sam1 = new Sample("父类 普通成员 sam1 初始化");
static Sample staticSam2 = new Sample("父类 静态成员 staticSam2 初始化");
static {
System.out.println("父类 static块 2 执行");
}
Father() {
System.out.println("父类 默认构造函数被调用");
}
Sample sam2 = new Sample("父类 普通成员 sam2 初始化");
{
System.out.println("父类 非静态块 2 执行");
}
}
class Son extends Father {
{
System.out.println("子类 非静态块 1 执行");
}
static Sample staticSamSub1 = new Sample("子类 静态成员 staticSamSub1 初始化");
Son() {
System.out.println("子类 默认构造函数被调用");
}
Sample sam1 = new Sample("子类 普通成员 sam1 初始化");
static Sample staticSamSub2 = new Sample("子类 静态成员 staticSamSub2 初始化");
static {
System.out.println("子类 static块1 执行");
}
Sample sam2 = new Sample("子类 普通成员 sam2 初始化");
{
System.out.println("子类 非静态块 2 执行");
}
static {
System.out.println("子类 static块2 执行");
}
}
class Sample {
Sample(String s) {
System.out.println(s);
}
Sample() {
System.out.println("Sample默认构造函数被调用");
}
}
输出结果:
父类 static块 1 执行
父类 静态成员 staticSam1 初始化
父类 静态成员 staticSam2 初始化
父类 static块 2 执行
子类 静态成员 staticSamSub1 初始化
子类 静态成员 staticSamSub2 初始化
子类 static块1 执行
子类 static块2 执行
父类 非静态块 1 执行
父类 普通成员 sam1 初始化
父类 普通成员 sam2 初始化
父类 非静态块 2 执行
父类 默认构造函数被调用
子类 非静态块 1 执行
子类 普通成员 sam1 初始化
子类 普通成员 sam2 初始化
子类 非静态块 2 执行
子类 默认构造函数被调用
由输出结果可知,执行的顺序为:
- 父类静态代码区和父类静态成员
- 子类静态代码区和子类静态成员
- 父类非静态代码区和普通成员
- 父类构造函数
- 子类非静态代码区和普通成员
- 子类构造函数