源代码:
class Root{ static{ System.out.println("Root的静态初始化块"); } { System.out.println("Root的普通初始化块"); } { System.out.println("Root的无参数初始化块"); } } class Mid extends Root{ static{ System.out.println("Mid的静态初始化块"); } { System.out.println("Mid的普通初始化块"); } public Mid(){ System.out.println("Mid的无参数构造器"); } public Mid(String msg){ this(); System.out.println("Mid的带参数的构造器,其参数值:"+msg); } } class Leaf extends Mid{ static{ System.out.println("Leaf的静态初始化块"); } { System.out.println("Leaf的普通初始化块"); } public Leaf(){ super("疯狂java讲义"); System.out.println("执行Leaf的构造器"); } } public class Java11 { public static void main(String[] args) { new Leaf(); System.out.println(" "); new Leaf(); } }
运行结果:
1.初始化块只有两种,一种是static修饰的,另外一种是没有static修饰的,有static修饰的初始化块叫做静态初始化块;普通初始化块负责对对象执行初始化,静态初始化块则负责对类进行初始化;
2.初始化块执行的顺序是:先执行静态的初始化块,再执行动态的初始化块,但是在执行动态的初始化块的时候;要把构造器的因素考虑进来,即在程序中执行的初始化块的顺序是(此时考虑构造器):先执行完静态初始化块,然后按照非静态初始化和构造器的顺序由上至下依次执行;(上面的源代码就是例子)
3.虽然java允许在一个类里面定义两个普通初始化块,当时这其实是没有很大的意义的,因为初始化块是在创建java对象时隐式执行的,而且它总是全部执行,因此完全可以把多个普通初始化块合并成为一个初始化块;
4.如果有一段初始化处理代码对所有对象都完全相同,且无需接受任何的参数,就可以把这段初始化代码提取到初始化块中;
5.在编译了代码之后,初始化中的代码会被还原到每个构造其中,而且位于构造器所有代码的前面;
6.静态初始化块同样也属于类的静态成员,因此也需要遵循静态成员不能访问非静态成员的规则,因此静态初始化块不能访问非静态成员,包括不能访问实例变量和实例方法;
7.上面源代码中第二次引用构造器比第一次引用构造器少执行了三个静态初始化块,这是因为第一次初始化系统不存在Leaf类,所以要加载Leaf类,加载类是会引用静态初始化块的。而第二次中则由于Leaf类先前被加载了,所以系统以及存在了Leaf,不需要加载了。(在执行源代码中,类加载了一次就会一直存在于虚拟机中)
时间: 2024-11-13 03:46:51