問題:以下代碼的運作結果是什麼?某大廠的面試題
有一個父類:
public class Father{
private int i = test();
private static int j = method();
static{
System.out.print("(1)");
}
Father(){
System.out.print("(2)");
}
{
System.out.print("(3)");
}
public int test(){
System.out.print("(4)");
return 1;
}
public static int method(){
System.out.print("(5)");
return 1;
}
}
和一個子類
public class Son extends Father{
private int i = test();
private static int j = method();
static{
System.out.print("(6)");
}
Son(){
// super();//寫或不寫都在,在子類構造器中一定會調用父類的構造器
System.out.print("(7)");
}
{
System.out.print("(8)");
}
public int test(){
System.out.print("(9)");
return 1;
}
public static int method(){
System.out.print("(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)
分析:
/*
* 父類的初始化<clinit>:
* (1)j = method();
* (2)父類的靜态代碼塊
*
* 父類的執行個體化方法:
* (1)super()(最前)
* (2)i = test();
* (3)父類的非靜态代碼塊
* (4)父類的無參構造(最後)
*
* 非靜态方法前面其實有一個預設的對象this
* this在構造器(或<init>)它表示的是正在建立的對象,因為這裡是在建立Son對象,是以
* test()執行的是子類重寫的代碼(面向對象多态)
*
* 這裡i=test()執行的是子類重寫的test()方法
*/
/*
* 子類的初始化<clinit>:
* (1)j = method();
* (2)子類的靜态代碼塊
*
* 先初始化父類:(5)(1)
* 初始化子類:(10)(6)
*
* 子類的執行個體化方法<init>:
* (1)super()(最前) (9)(3)(2)
* (2)i = test(); (9)
* (3)子類的非靜态代碼塊 (8)
* (4)子類的無參構造(最後) (7)
*
* 因為建立了兩個Son對象,是以執行個體化方法<init>執行兩次
*
* (9)(3)(2)(9)(8)(7)
*/
子類的super代表父類的整個執行個體化方法
為什麼不會出現(4)?
因為方法的重寫問題
父類的執行個體方法走到第2步時,由于初始化的是子類,是以會調用子類的test()方法
建立了兩個Son對象,是以執行個體初始化方法執行了兩次
哪些方法不能被重寫:
final方法
靜态方法
private等子類中不可見的方法
靜态變量與靜态代碼塊是順序執行的
非靜态變量與非靜态代碼塊也是順序執行的
構造函數總是最後執行