【面試題】Java類初始化和執行個體初始化的順序
一、類初始化
1、一個類要建立執行個體需要先加載并初始化該類
(1)main方法所在的類需要先加載和初始化
copy
class Father{
private static int i = method();
private static int method() {
System.out.println("(2)");
return 1;
}
}
public class Son{
private static int i = method();
private static int method() {
System.out.println("(1)");
return 1;
}
public static void main(String[] args) {
}
輸出結果:
(1)
上述的例子Father類和Son類之間沒有繼承關系,但是Son類當中有main方法,是以根據上述規則“main方法所在的類需要先加載和初始化”,可得結果和輸出結果相符,都是輸出(1),且這時候隻有類初始化過程。
2、一個子類要初始化需要先初始化父類
private static int i = method();
private static int method() {
System.out.println("(2)");
return 1;
}
public class Son extends Father{
private static int i = method();
private static int method() {
System.out.println("(1)");
return 1;
}
public static void main(String[] args) {
}
(2)
這個例子和上一個例子相似,唯一的不同是Son類繼承了Father類,根據規則2,可以發現父類的靜态變量先行初始化,是以輸出結果是(2)然後再輸出(1)。
3、一個類初始化就是執行()方法
(1)()方法由靜态類變量顯示指派代碼和靜态代碼塊組成
(2)類變量顯示指派代碼和靜态代碼塊代碼從上到下順序執行
(3)()方法隻執行一次
根據規則3,我們可以設定下列對造組,由下列試驗得出的結果也佐證了規則3。
private static int j = method2();
private static int i = method1();
private static int method2() {
System.out.println("(2)");
return 0;
}
private static int method1() {
System.out.println("(1)");
return 0;
}
public static void main(String[] args) {
}
private static int i = method1(); //調換i和j的聲明順序
private static int j = method2();
private static int method2() {
System.out.println("(2)");
return 0;
}
private static int method1() {
System.out.println("(1)");
return 0;
}
public static void main(String[] args) {
}
二、執行個體初始化
1、執行個體初始化就是執行()方法
(1)()方法可能重載有多個,有幾個構造器就有幾個方法
(2)()方法由非靜态執行個體變量顯示指派代碼和非靜态代碼塊、對應構造器代碼組成
(3)非靜态執行個體變量顯示指派代碼和非靜态代碼塊代碼從上到下順序執行,而對應構造器的代碼最後執行
根據上述規則,還可以再設立對照組,可以發現非靜态執行個體變量和非靜态代碼塊的初始化順序是按從上到下的順序執行的。
{
System.out.println("(2)");
}
private int anInt = method();
private int method() {
System.out.println("(1)");
return 0;
}
{
System.out.println("(4)");
}
private int anInt = method();
private int method() {
System.out.println("(3)");
return 0;
}
public static void main(String[] args) {
Son son = new Son();
}
(4)
(3)
class Father {
private int anInt = method();
{
System.out.println("(2)");
}
private int method() {
System.out.println("(1)");
return 0;
}
public class Son extends Father {
private int anInt = method();
{
System.out.println("(4)");
}
private int method() {
System.out.println("(3)");
return 0;
}
public static void main(String[] args) {
Son son = new Son();
}
(4)每次建立執行個體對象,調用對應構造器,執行的就是對應的方法
(5)方法的首行是super()或super(實參清單),即對應父類的方法
根據上述第5點,可以發現父類的構造方法都是先于子類的構造方法執行,在初始化子類執行個體的時候,因為其實子類的構造方法當中固定有一個super()方法,用于執行父類的構造方法。
Father(){
System.out.println("Father的無參構造方法");
}
Son(){
System.out.println("Son的無參構造方法");
}
public static void main(String[] args) {
Son son = new Son();
}
Father的無參構造方法
Son的無參構造方法
三、方法重寫對執行個體初始化的影響
(1)父類執行個體變量初始化當中用到的是子類重寫的方法
private int anInt = method();
{
System.out.println("(2)");
}
public int method() {
System.out.println("(1)");
return 0;
}
private int anInt = method();
{
System.out.println("(4)");
}
public int method() { //這裡重寫了method()方法
System.out.println("(3)");
return 0;
}
public static void main(String[] args) {
Son son = new Son();
}
本文作者:sherlock_221c
本文連結:
https://www.cnblogs.com/SherLocked/p/12826572.html