首先,让我们用一个简单的程序来引入主题:
***********************程序*********************
package cn.kml.forserver20130730;
/**
* 定义一个用于测试自由块以及构造器执行顺序的父类
* @author 柯美玲 QQ:794950040
*/
public class Detail{
public static int a;
public Detail(){//构造器
System.out.println("Detail构造器");
}
{//非静态块
System.out.println("Detail非静态");
}
static{//静态块
System.out.println("Detail静态块");
}
public static void main(String[] args) {
System.out.println("main1");
Detail detail=new Detail();
}
}
***********************运行结果*********************
在此刻,你是不是觉得很神奇!为什么构造函数不是最先执行的?你是不是开始怀疑我的结果,
其实不用怀疑,谁试谁知道………………
在了解具体的原因之前,让我们先来看一下,当一个程序执行时,需要做哪些准备工作。
那当然就是类装载器要把程序装载到虚拟机上。装载过程分为三个部分:装载,链接和初始化。
其中链接又分为三部分:校验,解析,准备。下面分别列出具体作用:
装载:查找和导入类或接口的二进制数据
链接:进行下面三个步骤,其中解析步骤是可选择的。
校验:检查导入类或者接口的二进制数据是否正确
解析:将符号引用转成直接引用
准备:给类的静态变量分配并初始化储存空间
初始化:初始化静态变量以及执行静态块代码
如下图所示:
所以说,由上面可以得出,静态变量的分配空间与初始化以及静态自由块的执行都是在.class
文件加载时,也就是主函数执行之前。
总结:
**************************静态块与非静态块***************************
java中一个类中除了有属性,方法之外,还可以有自由块。
自由块又可以分为静态块和非静态块。
虽同为自由块,但静态块和非静态块的执行是有很大区别的。
由本文最初给出的程序及结果可知:
静态块最先执行,而且只会执行一次;
而非静态块是在每次实例化类的对象时执行的,而且执行在构造器之前。
***********************静态属性与一般属性**************************
静态属性的初始化是在类装载过程中切只执行一次,先于主函数的执行
非静态属性的初始化在实例化对象时,先于构造器的执行
当类与类之间存在继承关系时:如下
package cn.kml.forserver20130730;
/**
* 定义一个用于测试自由块以及构造器执行顺序的子类,继承Detail类
* @author 柯美玲 QQ:794950040
*/
public class subDetail extends Detail{
public subDetail(){//构造器
System.out.println("subDetail构造器");
}
{ //非静态块
System.out.println("subDetail非静态块");
}
static { //静态块
System.out.println("subDetail静态块");
}
public static void main(String args[]){
System.out.println("subDetailmain");
subDetail te=new subDetail();
}
}
运行结果:
当存在继承关系时,先执行父类的静态块,再执行子类的静态块
接下来执行子类的主函数
若实例化子类的对象,先执行父类的非静态块,再执行父类的构造函数
然后执行子类的非静态块,最后执行子类的构造函数
再如以下程序:
package cn.kml.forserver20130730;
/**
* 定义一个用于测试自由块以及构造器执行顺序的子类,继承subDetail类
* @author 柯美玲 QQ:794950040
*/
public class subbDetail extends subDetail{
public subbDetail(){//构造器
System.out.println("subbDetail构造器");
}
static{//静态块
System.out.println("subbDetail静态快");
}
{//非静态块
System.out.println("subbDetail非静态快");
}
public static void main(String[] args) {
System.out.println("subbDetail main");
subbDetail sDetail = new subbDetail();
}
}
运行结果:
由以上结果显而易见,自由块与构造器的执行顺序。
纪念整整崩了15次的google浏览器!!