public class Test08 { public static void main(String[] args) { Zi zi = new Zi(); } } class Fu{ private static int i = getNum("(1)i"); private int j = getNum("(2)j"); static{ print("(3)父类静态代码块"); } { print("(4)父类非静态代码块,又称为构造代码块"); } Fu(){ print("(5)父类构造器"); } public static void print(String str){ System.out.println(str + "->" + i); } public static int getNum(String str){ print(str); return ++i; } } class Zi extends Fu{ private static int k = getNum("(6)k"); private int h = getNum("(7)h"); static{ print("(8)子类静态代码块"); } { print("(9)子类非静态代码块,又称为构造代码块"); } Zi(){ print("(10)子类构造器"); } public static void print(String str){ System.out.println(str + "->" + k); } public static int getNum(String str){ print(str); return ++k; } }
public class T { public static int k = 0; public static T t1 = new T("t1"); public static T t2 = new T("t2"); public static int i = print("i"); public static int n = 99; public int j = print("j"); static{ print("静态块"); } { print("构造块"); } public T(String str){ System.out.println((++k) + ":" + str + " i=" + i + " n=" + n); ++n; ++i; } public static int print(String str){ System.out.println((++k) + ":" + str + " i=" + i + " n=" + n); ++n; return ++i; } public static void main(String[] args) { } }
首先看到static关键字,脑子里面第一反应有几点,
1、公有属性,可以有类名称直接访问。
2、静态方法,可以有类名称直接方法。
3、静态方法或者属性,可以再对象实例化之前就调用
至于该题中,顺序执行,先执行public static int k =0 ;
因为没有输出不用考虑这个,接着public static Text t1 = new Text("t1") ;
在t1对象初始化时先执行非静态方法或者非静态常量,顺序执行,接着运行构造参数,
根据程序来看应该打印三条记录,分别是
1:j i=0 n=02:构造块 i=1 n=13:t1 i=2 n=2
接下来public static Text t2 = new Text("t2") ;同理,执行完之后继续执行static代码块或者赋值静态变量,在main()方法中new了一个新的实例,静态变量只执行一次,接下来就是顺序执行非静态方法---->构造方法。
动态初始化块在每次实例化对象时在构造函数之前执行
······多个动态成员变量与动态初始化块参照出现顺序先后执行······
总结:总的来说,在不涉及继承的前提下,当首次加载类时,按照如下顺序执行
按照出现顺序先后执行静态成员变量定义与静态初始化块
按照出现顺序先后执行动态成员变量定义与动态初始化块
执行构造函数
再次实例化对象时只执行第2、3步即可
············成员变量与定义与初始化块先于构造函数执行·········
1、执行父类的静态成员变量定义与静态初始化块,执行子类的静态成员变量定义与静态初始化块
2、执行父类的非静态成员变量定义与动态初始化块,执行父类构造方法
3、执行子类的非静态成员变量定义与动态初始化块,执行子类构造方法
另:父类构造方法中用到的方法如果已被子类重写,那么在构造子类对象时在调用父类构造函数中使用子类重写的方法