在类的内部,变量定义的先后顺序决定了初始化的顺序。即变量定义散布于方法定义之间,他们仍旧会在任何方法(包括构造器)被调用之前得到初始化。
static 修饰的是属于类的,只有一份被对象所共有
************************************************************
************************************************************
参考:java类初始化顺序
- public
class InitialOrderTest { -
-
// 静态变量 -
public static String staticField = "静态变量"; -
// 变量 -
public String field = "变量"; -
-
// 静态初始化块 -
static { -
System.out.println(staticField); -
System.out.println("静态初始化块"); -
} -
-
// 初始化块 -
{ -
System.out.println(field); -
System.out.println("初始化块"); -
} -
-
// 构造器 -
public InitialOrderTest() { -
System.out.println("构造器"); -
} -
-
public static void main(String[] args) { -
new InitialOrderTest(); -
} - }
运行以上代码,我们会得到如下的输出结果:
- 静态变量
- 静态初始化块
- 变量
- 初始化块
- 构造器
*******************************************************
*******************************************************
思考:改变构造器 初始化块 静态初始化块顺序
- public
class InitialOrderTest { -
-
// 静态变量 -
public static String staticField = "静态变量"; -
// 变量 -
public String field = "变量"; -
-
// 构造器 -
public InitialOrderTest() { -
System.out.println("构造器"); -
} -
// 初始化块 -
{ -
System.out.println(field); -
System.out.println("初始化块"); -
} -
// 静态初始化块 -
static { -
System.out.println(staticField); -
System.out.println("静态初始化块"); -
} -
-
public static void main(String[] args) { -
new InitialOrderTest(); -
} - }
**************************
output:
静态变量
静态初始化块
变量
初始化块
构造器
***************************
结论:代码顺序的改变不会改变输出的顺序。
*******************************************************
*******************************************************
思考二:在初始化块添加输出静态变量语句。
- public
class InitialOrderTest { -
-
// 静态变量 -
public static String staticField = "静态变量"; -
// 变量 -
public String field = "变量"; -
-
// 静态初始化块 -
static { -
System.out.println(staticField); -
System.out.println("静态初始化块"); -
} -
-
// 初始化块 -
{ -
System.out.println(field); -
System.out.println("初始化块"); -
System.out.println(staticField); -
} -
-
// 构造器 -
public InitialOrderTest() { -
System.out.println("构造器"); -
} -
-
public static void main(String[] args) { -
new InitialOrderTest(); -
} - }
******************************
output:
静态初始化块
变量
初始化块
静态变量
构造器
******************************
疑问:输出变了。静态变量只输出一次,且是初始化块中输出。
*******************************************************
*******************************************************
这与上文中说的完全符合。那么对于继承情况下又会怎样呢?我们仍然以一段测试代码来获取最终结果:
- class
Parent { -
// 静态变量 -
public static String p_StaticField = "父类--静态变量"; -
// 变量 -
public String p_Field = "父类--变量"; -
-
// 静态初始化块 -
static { -
System.out.println(p_StaticField); -
System.out.println("父类--静态初始化块"); -
} -
-
// 初始化块 -
{ -
System.out.println(p_Field); -
System.out.println("父类--初始化块"); -
} -
-
// 构造器 -
public Parent() { -
System.out.println("父类--构造器"); -
} - }
-
- public
class SubClass extends Parent { -
// 静态变量 -
public static String s_StaticField = "子类--静态变量"; -
// 变量 -
public String s_Field = "子类--变量"; -
// 静态初始化块 -
static { -
System.out.println(s_StaticField); -
System.out.println("子类--静态初始化块"); -
} -
// 初始化块 -
{ -
System.out.println(s_Field); -
System.out.println("子类--初始化块"); -
} -
-
// 构造器 -
public SubClass() { -
System.out.println("子类--构造器"); -
} -
-
// 程序入口 -
public static void main(String[] args) { -
new SubClass(); -
} - }
运行一下上面的代码,结果马上呈现在我们的眼前:
- 父类--静态变量
- 父类--静态初始化块
- 子类--静态变量
- 子类--静态初始化块
- 父类--变量
- 父类--初始化块
- 父类--构造器
- 子类--变量
- 子类--初始化块
- 子类--构造器
*******************************************************
*******************************************************
- public
class TestOrder { -
// 静态变量 -
public static TestA a = new TestA(); -
-
// 静态初始化块 -
static { -
System.out.println("静态初始化块"); -
} -
-
// 静态变量 -
public static TestB b = new TestB(); -
-
public static void main(String[] args) { -
new TestOrder(); -
} - }
-
- class
TestA { -
public TestA() { -
System.out.println("Test--A"); -
} - }
-
- class
TestB { -
public TestB() { -
System.out.println("Test--B"); -
} - }
运行上面的代码,会得到如下的结果:
- Test--A
- 静态初始化块
- Test--B
*******************************************************
*******************************************************
参考:JAVA 初始化顺序
//JAVA初始化分两大步
//A、类的加载
//
//
//
//
//
//
//
//B、类的实例化
//
//
//
//
//
//
//注:类装载步骤(详解A步骤)
//
//装载:查找和导入类或接口的二进制数据;
//链接:执行下面的校验、准备和解析步骤,其中解析步骤是可以选择的;
//校验:检查导入类或接口的二进制数据的正确性;
//准备:给类的静态变量分配并初始化存储空间;
//解析:将符号引用转成直接引用;
//初始化:激活类的静态变量的初始化Java代码和静态Java代码块。
//初始化类中属性是静态代码块的常用用途,但只能使用一次。