類初始化過程
- 一個類要創建實例需要先加載並初始化該類
a.main方法所在的類需要先加載和初始化
2.一個子類要初始化要先初始化父類
3.一個類初始化就是執行<clinit>()方法
a.<clinit>()方法由靜態類變量顯示賦值代碼和靜態代碼塊組成
b.靜態類變量顯示賦值代碼和靜態代碼塊代碼是從上到下按順序執行的
c.<clinit>()方法只執行一次
實例初始化過程
- 實例初始化就是執行<init>()方法
a.<init>()方法可能重載有多個,有幾個構造器就有幾個<init>()方法
b.<init>()方法由非靜態實例變量顯示賦值代碼和非靜態代碼塊、對應構造器代碼組成
c.非靜態實例變量顯示賦值代碼和非靜態代碼塊代碼從上到下按順序執行,而對應構造器的代碼最後執行
d.每次創建實例對象,調用對應構造器,執行的就是對應的<init>方法
e.<init>方法的首行是super()或super(實參列表),即父類的<init>方法
通過上面知識點一起看下面這個“父子”面試題
Father.java
package com.java_foundation.test_1;
/**
* @program: java_foundation
* @description: 父類
* 類初始化 clinit
* 1)靜態類變量賦值 j = method()
* 2)父類的靜態代碼塊
* 類的實例化方法 init
* 1)super()(最前)
* 2)非靜態變量賦值 i = test()
* 3)子類的非靜態代碼塊
* 4)子類的無參構造(最後)
*
* 非靜態方法前面其實有一個默認的對象this
* this在構造器表示正在創建對象,因爲這裏是在創建子類對象。所以test()執行的
* 是子類重寫的代碼(多態)
*
* i=test()執行子類的test()
* @author: xiongbangwen <Email>[email protected]</Email>
* @create: 2020-05-30 22:32
**/
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;
}
}
Son.java
package com.java_foundation.test_1;
/**
* @program: java_foundation
* @description: 子類
* 先初始化父類 Father
* 再初始化子類 Son
* 類初始化 clinit
* 1)靜態類變量賦值 j = method()
* 2)父類的靜態代碼塊
* 類的實例化方法 init 對象創建幾次就走幾次
* 1)super()(最前)
* 2)非靜態變量賦值 i = test()
* 3)子類的非靜態代碼塊
* 4)子類的無參構造(最後)
*
* @author: xiongbangwen <Email>[email protected]</Email>
* @create: 2020-05-30 22:32
**/
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;
}
}
Test.java
package com.java_foundation.test_1;
/**
* @program: java_foundation
* @description: 測試類
* @author: xiongbangwen <Email>[email protected]</Email>
* @create: 2020-05-30 22:33
**/
public class Test {
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)
}
}
方法的重寫Override
- 哪些方法不可以被重寫
final方法 、 靜態方法 、private 等子類不可見的
2.對象的多態性
a.子類如果重寫了父類的方法,通過子類對象調用的一定是子類重寫過的代碼
b.非靜態方法默認的調用對象是this
c.This對象在構造器或init方法中就是正在創建的對象
Override和 overload的區別?
Override是讓類以統一的方式處理不同類型數據的一種手段,實質表現就是多個具有不同的參數個數或者類型的同名函數(返回值類型可隨意,不能以返回類型作爲重載函數的區分標準)同時存在於同一個類中,是一個類中多態性的一種表現(調用方法時通過傳遞不同參數個數和參數類型來決定具體使用哪個方法的多態性)。
overload是父類與子類之間的多態性,實質是對父類的函數進行重新定義,如果在子類中定義某方法與其父類有相同的名稱和參數則該方法被重寫,不過子類函數的訪問修飾權限不能小於父類的;若子類中的方法與父類中的某一方法具有相同的方法名、返回類型和參數表,則新方法將覆蓋原有的方法,如需父類中原有的方法則可使用 super 關鍵字。