Java类的初始化顺序
下面的程序说明子父类中成员变量的构造顺序
abstract class SupConstruction
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/
ContractedBlock.gif) … {
SupConstruction()
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) … {
System.out.println( " SupConstruction constructed! " );
con();
System.out.println( " con " );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
abstract void con(); // 虚拟函数
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kEnd.gif) }
public class Construction extends SupConstruction // 继承虚拟类
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/
ContractedBlock.gif) … {
int i = 9 ;
Construction()
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) … {
super (); // 调用构造函数
System.out.println( " Construction constructed " + i);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
public void con() // 超越虚拟方法
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) … {
System.out.println( " Con " + i);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
public static void main(String [] args)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) … {
Construction c = new Construction(); // 实例化.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kEnd.gif) }
输出结果:
SupConstruction constructed!
Con 0
con
Construction constructed 9
其中的Con 0说明在此时i已经被声明,并且被赋上初值(或者说该变量所占的内存空间被清空)。同时也说明i=9,还没有被执行。上面程序的顺序是这样的:当new
一个Construction的时候,调用Construction的构造函数。然后进入父类的构造函数。而在进入Construction的构造函数之前 或许
int i已经被执行(这点以后还会说明为什么),但i=9没有被执行。进入父类的构造函数函数后打印SupConstruction
constructed!,然后调用自己的虚方法。因为多态的机制,函数将调用子类的同名方法。在那里打印Con
0。然后返回到父类打印con,再返回子类的构造函数打印Construction constructed 9。结束构造。
下面讲讲为什么说进入Construction的构造函数之前或许int i已经被执行。看下面的例子:
class Test
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/
ContractedBlock.gif) … {
int t1 = 3 ;
static int t2 = 4 ;
static
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) … {
System.out.println( " Static block " + " t2: " + t2);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
public Test()
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) … {
System.out.println( " Construct:t1: " + t1 + " t2: " + t2);
t1 = 30 ;
t2 = 40 ;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) … {
t2 = 9 ;
System.out.println( " nonstatic,t1: " + t1 + " t2: " + t2);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
public static void TestClass()
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) … {
System.out.println( " Static Method: " + " t2: " + t2);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kEnd.gif) }
public class Life
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/
ContractedBlock.gif) … {
public static void main(String [] args)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) … {
Test.TestClass();
Test t = new Test();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kEnd.gif) }
打印结果:
Static block t2:4
Static Method:t2:4
nonstatic,t1:3t2:9
Construct:t1:3t2:9
这说明在执行构造函数之前nonstatic块就已经被执行。而且看出了初始化顺序static变量->static块->非static变量->非static块-
构造函数。但是不是真的是这样?看下面的例子:
class SupTest
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/
ContractedBlock.gif) … {
int st1 = 12 ;
static int st2 = 19 ;
public SupTest( int x)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) … {
st1 = x;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kEnd.gif) }
class Test extends SupTest
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/
ContractedBlock.gif) … {
int t1 = 3 ;
static int t2 = 4 ;
static
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) … {
System.out.println( " super static : " + " t2: " + SupTest.st2);
System.out.println( " Static block " + " t2: " + t2);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
public Test()
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) … {
super (t1);
System.out.println( " Construct:t1: " + t1 + " t2: " + t2);
t1 = 30 ;
t2 = 40 ;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) … {
t2 = 9 ;
System.out.println( " nonstatic,t1: " + t1 + " t2: " + t2);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
public static void TestClass()
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) … {
System.out.println( " Static Method: " + " t2: " + t2);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kEnd.gif) }
public class Life
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/
ContractedBlock.gif) … {
public static void main(String [] args)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) … {
Test.TestClass();
Test t = new Test();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kEnd.gif) }
打印结果:
Life.java:24: 无法在调用父类型构造函数之前引用 t1
super(t1);
^
1 错误
可惜编译的时候就报错。然后将 super(t1);改为 super(t2)编译运行成功。
这说明在调用父类构造函数前,子类的t1并没有声明并被缺省初始化。然后对于第一个程序在子类Construction 中添加非静态块打印i;得到打印结果:
SupConstruction constructed!
Con 0
con
9
Construction constructed 9
这就道出了真正的构造顺序:(结合static只属于类的经验)
加载class路径->static变量初始化->static块->进入子类构造函数->进入父类构造函数->父类虚方法下传->子类非static变量声明并清空
相应的内存空间->多态机制,子类同名函数调用->父类构造函数退出->子类非static变量赋值->子类非static块调用->子类构造函数退出->对象构造完
成。