一、示例代码
package javaDemo;
class Parent {
public static String p_StaticField1 = "父类--静态变量1";
// 变量
public String p_Field = "父类--变量";
protected int i = 9;
protected int j = 0;
// 静态初始化块
static {
System.out.println(p_StaticField1);
System.out.println("父类--静态初始化块");
}
// 初始化块
{
System.out.println(p_Field);
System.out.println("父类--初始化块");
}
public static String p_StaticField2 = "父类--静态变量2";
// 构造器
public Parent() {
System.out.println("父类--构造器");
System.out.println("i=" + i + ", j=" + j);
j = 20;
}
public static String p_StaticField3 = "父类--静态变量3";
}
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("子类--构造器");
j = -1;
System.out.println("i=" + i + ",j=" + j);
}
// 程序入口
public static void main(String[] args) {
System.out.println("子类main方法");
new SubClass();
}
public static String s_StaticField2 = "子类--静态变量1";
}
二、java中的初始化顺序:
1、父类static变量和语句块(顺序依赖于定义的顺序)
2、子类static变量和语句块
3、父类的直接初始化块
4、父类的构造函数
5、子类的初始化块
6、子类的构造函数
三、原因:
1、jvm首先是加载类,内部做了链接操作之后,才能执行代码,所以加载一定在执行以先,所以static的一定早于别的;
加载的时候是先加载父类的,所以父类static的早于子类static
2、所有子类的构造函数第一句 一定是 调用父类构造函数,所以4在6以先。
3、按着顺序貌似3应该在5后,即顺序是 1 2 5 3 4 6 ,但是这样会导致 子类先初始化,父类后初始化,进而导致语义错误(子类没法覆盖流程),所以顺序必须是父类完全处理结束之后才开始处理子类
4、初始化块在编译期就可以确定初始化顺序(语义上不是编译期,java都是在jvm中执行),而构造函数是一个函数,在运行时才能执行,所以初始化块在前