静态初始化块
基本概念:
1、如果定义初始化块时使用了static 修饰符,则这个初始化块就变成了静态初始化块,也被称为类初始化块(普通初始化块负责对对象执行初始化,类初始化块则负责对类进行初始化)
2、静态初始化块是类相关的 系统将在类初始化阶段执行静态初始化块,而不是在创建对象时才执行 因此静态初始化块总是比普通初始化块先执行
3、静态初始化块是类相关的 ,通常用于对整个类进行初始化处理,通常用于对类变量执行初始化处理。静态初始化块不能对实例变量进行初始化处理
4、静态初始化块也被称为类初始化块,也属于类的静态成员,同样需要遵循静态成员不能访问非静态成员的规则,因此静态初始化块不能访问非静态成员,包括不能访问实例变量和实例方法
5、与普通初始化块类似的是,系统在类初始化阶段执行静态初始化块时,不仅会执行本类的静态初始化块,而且还会一直上溯到 java.lang.Object
类(如果它包含静态初始化块)
先执行 java .lang.Object类的静态初始化块(如果有),然后执行其父类的静态初始化块……最后才执行该类的静态初始化块,经
过这个过程,才完成了该类的初始化过程。
只有当类初始化完成后,才可以在系统中使用这个类,包括问这个类的类方法、类变量或者用这个类来创建实例
class Root {
static {
System.out.println("Root的--静态初始化代码块");
}
{
System.out.println("Root的--普通初始化代码块");
}
public Root(){
System.out.println("Root的--无参构造");
}
}
class Mid extends Root{
static {
System.out.println("Mid的--静态初始化代码块");
}
{
System.out.println("Mid的--普通初始化代码块");
}
public Mid(){
System.out.println("Mid的--无参构造");
}
public Mid(String msg){
//通过 this 调用同一类中重载的构造器
this () ;
System.out.println("Mid 的带参数构造器,其参数值:"+msg);
}
}
class Leaf extends Mid{
static {
System.out.println("Leaf的--静态初始化代码块");
}
{
System.out.println("Leaf的--普通初始化代码块");
}
public Leaf(){
// 通过 super 调用父类中有一个字符串参数的构造器
super("正在 -- 调用父类中有一个字符串参数的构造器" ) ;
System.out.println("Leaf的--无参构造");
}
}
public class Tests {
public static void main(String[] args) {
new Leaf() ;
new Leaf() ;
}
}
Root的--静态初始化代码块
Mid的--静态初始化代码块
Leaf的--静态初始化代码块
Root的--普通初始化代码块
Root的--无参构造
Mid的--普通初始化代码块
Mid的--无参构造
Mid 的带参数构造器,其参数值:正在 -- 调用父类中有一个字符串参数的构造器
Leaf的--普通初始化代码块
Leaf的--无参构造
Root的--普通初始化代码块
Root的--无参构造
Mid的--普通初始化代码块
Mid的--无参构造
Mid 的带参数构造器,其参数值:正在 -- 调用父类中有一个字符串参数的构造器
Leaf的--普通初始化代码块
Leaf的--无参构造
Process finished with exit code 0
第一次创建 Leaf 对象时,因为系统中还不存在 Leaf 类,因此需要先加载并初始化 Leaf 类,
初始化 Leaf 类时会先执行其顶层父类的静态初始化块,再执行其直接父类的静态初始化块,最后才执行 Leaf 本身的静态初始化块
一旦Leaf 类初始化成功后, Leaf 类在该虚拟机里将一直存在,因此当第一创建 Leaf 实例时无须再次对 Lea 类进行初始化
每次创建 Leaf 对象时,都需要
先执行最顶层父类的初始 块、构造器 … ,然后执行其父类的初始化块、构造器……最后才执行 Leaf 类的初始化块和构造器
Java 系统加载并初始化某个类时,总是保证该类的所有父类(包括直接父类和间接父类)全部加载并初始化
静态初始化块和声明静态成员变量时所指定的初始值都是该类的初始化代码,它们的执行顺序与源程序中的排列顺序相同。
public class StaticlnitTest{
//先执行静态初始化块将a静态成员变量赋值为6
static{
a = 6;
}
//再将a静态成员变量赋值为9
static int a = 9;
public static void main(String[] args) {
//下面代码将输出
System out println(StaticlnitTest.a);
}
}
程序中定义了两次对 a 静态成员变量进行赋值,执行结果是 a 值为 9,这表明 static int a =9 这行代码位于静态初始化块之后执行。
如果将 a = 6与 static int a = 9; 调换顺
序,将可以看到程序输出6 ,这是由于静态初始化块中代码再次将 a 的值设为6