class Test2_Extends { public static void main(String[] args) { Zi z = new Zi(); } } class Fu { static { System.out.println("静态代码块Fu"); } { System.out.println("构造代码块Fu"); } public Fu() { System.out.println("构造方法Fu"); } } class Zi extends Fu { static { System.out.println("静态代码块Zi"); } { System.out.println("构造代码块Zi"); } public Zi() { System.out.println("构造方法Zi"); } }
考题分析步骤如下:
1>找到代码中的main方法,把main方法所在类进方法区。在此时发现main方法所在的Test2_Extends类中创建了一个叫z的对象。
2>找到该对象所属的类Zi,发现它有继承Fu,所以在把Zi类写进方法区之前先把Fu类写进方法区,进而创建对象。
3>因为Fu类中是有静态代码块,静态代码块是随着类的加载而加载,且只执行一次,所以在加载Fu类的同时,Fu类的静态代码块加载执行,输出的第一句话出现“静态代码块Fu,紧接著是第二句“静态代码块Zi”。
4>类加载完毕走zi类的构造方法来初始化。而java是分层初始化的,所以通过子类的构造方法中的默认super();访问到父类的构造方法,发现父类中存在构造代码块,构造代码块是优先于构造函数执行的,所以先输出“构造代码块Fu”,再输出“构造方法Fu”。父类初始化完毕子类开始初始化,输出“构造代码块Zi”,“构造代码块Zi”。
注意事项总结:
1.子类的所以构造方法都会默认访问父类的空参构造方法,初始化分层。
2.静态代码块是随着类的加载而加载,跟是否创建对象无关,只执行一次。
3.构造代码块位于类中方法外,每创建一次对象就会执行一次,且优于构造函数执行。
附代码运行结果图: