一个实例来理解类的加载及对象的创建过程
package com.xsl.test; class Father{ private int i = test(); private static int j = method(); static{ System.out.println("(1)"); } Father(){ System.out.println("(2)"); } { System.out.println("(3)"); } public int test(){ System.out.println("(4)"); return 1; } public static int method(){ System.out.println("(5)"); return 1; } } public class Son extends Father { private int i = test(); private static int j = method(); static { System.out.println("(6)"); } Son() { System.out.println("(7)"); } { System.out.println("(8)"); } public int test(){ System.out.println("(9)"); return 1; } public static int method(){ System.out.println("(10)"); return 1; } public static void main(String[] args) { Son s1 = new Son(); System.out.println(); Son s2 = new Son(); } /**运行结果是 (5) (1) (10) (6) (9) (3) (2) (9) (8) (7) (9) (3) (2) (9) (8) (7) 先加载父类静态属性,其中父类的静态属性调用父类的静态方法、再加载父类的静态代码块 [此处分别输出(5)、(1)] 注意:如果静态属性不调用静态方法的话,静态方法就不加载,即(5)不会被输出 再加载子类静态属性,其中子类的静态属性调用子类的静态方法、再加载子类的静态代码块 [此处分别输出(10)、(6)] 注意:如果静态属性不调用静态方法的话,静态方法就不加载,即(10)不会被输出 再加载父类的一般属性,其中属性i调用的test()方法被子类重写了,所以父类的属性i调用子类的test()方法 [此处输出(9)] 再加载父类的代码块、父类的构造方法 [此处分别输出(3)、(2)] 再加载子类的一般属性,其中属性i调用test()方法 [此处输出(9)] 再加载子类的代码块、子类的构造方法[此处分别输出(8)、(7)] 第二次再new出一个子类的对象时,因为在第一次运行时静态方法、静态代码块就加载出来了存放在静态区,程序结束后系统才会释放,所以在程序运行时不会再加载第二次 给静态成员变量赋值和静态代码块的先后执行顺序是看代码的先后顺序 假设该类是第一次进行实例化。那么有如下加载顺序 静态总是比非静态优先,从早到晚的顺序是: 静态代码块和静态成员变量的顺序根据代码位置前后来决定。 代码块和成员变量的顺序也根据代码位置来决定 最后才调用构造方法构造方法 */ }