对于Java的源程序,我们一般需要经过编译与运行两个步骤,源程序经过编译生成字节码文件,字节码文件又被加载到java的虚拟机中。如下图:
那么,在加载的时候,按一个什么样的顺序进行加载的?下面将通过一个具体的实例来分析一下。
public class Demo01 {
static {
System.out.println("静态代码块Demo01");
}
public static void main(String[] args) {
System.out.println("main方法");
A a = new A();
A a2 = new A();
System.out.println(B.density);
System.out.println(C.y);
System.out.println(C.x);
}
}
class A extends A_Father {
public static int width = 100;
public static final int heigth = 200;
static {
System.out.println("静态代码块A");
width = 300;
}
public A() {
System.out.println("构造方法A");
}
}
class A_Father {
public static int capacity = 300;
public static int high = 50;
static {
System.out.println("静态代码块A_Father");
}
public A_Father() {
System.out.println("构造方法A_Father");
}
}
class B {
public static final double density = 0.52;
static {
System.out.println("静态代码块B");
}
}
class C extends C_Father {
public static int x = 12;
static {
System.out.println("静态代码块C");
}
}
class C_Father {
public static int y = 12;
static {
System.out.println("静态代码块C_Father");
}
}
代码开始由public这个类开始,加载这个类的时候,首先看有没有静态的属性,以及静态的代码块(这里有
静态代码块Demo01),然后是main这个主方法,打印(
main方法),然后是A a语句,这时候加载类A,因为A有父类,先加载父类,对于父类还是先看其有没有静态的属性,代码块,这里父类打印(
静态代码块A_Father),然后是子类的静态代码块(
静态代码块A),再执行语句new A,同样先打印父类(
构造方法A_Father)然后是子类的构造方法(
构造方法A)再次执行A a2的时候,不会再进行加载了,
new A()的时候,构造方法还是会进行调用打印
(构造方法A_Father)和
(构造方法A)。在执行B.density的时候,因为其为final类型的,则其类不会加载。然后是C.y,直接加载父类C_Father,则打印(
静态代码块C_Father),然后在执行C.x,加载类C,打印(
静态代码块C)