Java初始化顺序
本文内容纲要:
1无继承情况下的Java初始化顺序:
classSample
{
Sample(Strings)
{
System.out.println(s);
}
Sample()
{
System.out.println("Sample默认构造函数被调用");
}
}
classTest{
staticSamplesam=newSample("静态成员sam初始化");
Samplesam1=newSample("sam1成员初始化");
static{
System.out.println("static块执行");
if(sam==null)System.out.println("samisnull");
sam=newSample("静态块内初始化sam成员变量");
}
Test()
{
System.out.println("Test默认构造函数被调用");
}
}
//主函数
publicstaticvoidmain(Stringstr[])
{
Testa=newTest();
}
输出结果为:
静态成员sam初始化-----静态成员初始化
static块执行-----静态块被执行
静态块内初始化sam成员变量----静态块执行
*sam1成员初始化-----*普通成员初始化
Test默认构造函数被调用-----构造函数执行
由此可以得出结论:
a静态成员变量首先初始化(注意,Static可以看做一个静态成员,其执行顺序和其在类中申明的顺序有关)
b普通成员初始化
c执行构造函数。
对于静态成员(static块可以看成普通的一个静态成员,其并不一定在类初始化时首先执行)和普通成员,其初始化顺序只与其在类定义中的顺序有关,和其他因素无关。
例如下面的例子:
classTest{
static{
System.out.println("static块1执行");
}
staticSamplestaticSam1=newSample("静态成员staticSam1初始化");
Samplesam1=newSample("sam1成员初始化");
staticSamplestaticSam2=newSample("静态成员staticSam2初始化");
static{
System.out.println("static块2执行");
}
Test()
{
System.out.println("Test默认构造函数被调用");
}
Samplesam2=newSample("sam2成员初始化");
}
则结果为:
static块1执行
静态成员staticSam1初始化
静态成员staticSam2初始化
static块2执行
--------静态成员
sam1成员初始化
sam2成员初始化
--------普通成员
Test默认构造函数被调用
--------构造函数
2Java继承情况下的初始化顺序:
classTest{
static{
System.out.println("父类static块1执行");
}
staticSamplestaticSam1=newSample("父类静态成员staticSam1初始化");
Samplesam1=newSample("父类sam1成员初始化");
staticSamplestaticSam2=newSample("父类静态成员staticSam2初始化");
static{
System.out.println("父类static块2执行");
}
Test()
{
System.out.println("父类Test默认构造函数被调用");
}
Samplesam2=newSample("父类sam2成员初始化");
}
classTestSubextendsTest
{
staticSamplestaticSamSub=newSample("子类静态成员staticSamSub初始化");
TestSub()
{
System.out.println("子类TestSub默认构造函数被调用");
}
Samplesam1=newSample("子类sam1成员初始化");
staticSamplestaticSamSub1=newSample("子类静态成员staticSamSub1初始化");
static{System.out.println("子类static块执行");}
Samplesam2=newSample("子类sam2成员初始化");
}
执行结果:
父类static块1执行
父类静态成员staticSam1初始化
父类静态成员staticSam2初始化
父类static块2执行
--------父类静态成员初始化
子类静态成员staticSamSub初始化
子类静态成员staticSamSub1初始化
子类static块执行
-------子类静态成员初始化
父类sam1成员初始化
父类sam2成员初始化
父类Test默认构造函数被调用
-------父类普通成员初始化和构造函数执行
子类sam1成员初始化
子类sam2成员初始化
子类TestSub默认构造函数被调用
-------父类普通成员初始化和构造函数执行
由此得出Java初始化顺序结论:
1继承体系的所有静态成员初始化(先父类,后子类)
2父类初始化完成(普通成员的初始化-->构造函数的调用)
3子类初始化(普通成员-->构造函数)
Java初始化顺序如图:
有的朋友问到内部的机制,上述的初始化顺序是由下面的几条规则决定的:
1.首先初始化静态域是因为静态域是放在方法区和class对象在一起的。
2.由于类加载的时候,会向上查找基类,因为子类的初始化依赖于基类首先初始化。所以会首先发生“基类->子类"顺序的类加载,类加载过程中,顺便完成了静态域的初始化。
3.另外一条规则是初始化块和域的初始化按照声明的顺序进行。
详见thinkinginjava中译本第四版的P147页。
本文内容总结:
原文链接:https://www.cnblogs.com/miniwiki/archive/2011/03/25/1995615.html