Java過載、重寫、覆蓋、隱藏的總結
過載Overloading
發生要素如下:
1. 在同一作用範圍內(同一個類,同一個介面)
2. 方法名必定相同
3. 形參組成不同(型別、個數均不相同 or 個數相同但型別不同 or 型別相同個數不同)
錯誤的認識:
1. 方法名相同,形參組成完全相同,返回型別不同也算過載(報錯)
2. 有abstract修飾才算過載(無所謂啊,修飾符惹誰了?)
abstract class AbstractBase { abstract void add(); abstract void add(int a); //OK void add(String b){} //OK int add(String b){} // NO!!!編譯不通過 protected void add(int a,int b){} }
覆蓋/重寫/覆寫(一個意思!)(Overriding/Overwrite)
發生要素如下:
1. 不同作用範圍內(繼承別的類,實現介面)
2. 方法名相同(廢話!)
3. 形參組成相同(型別、個數均相同)
4. 返回型別相同
個人理解:
1. 既然是覆蓋,要完全蓋住,學的像點,所以方法的外表要看上去一樣嘛。
2. 實現介面方法,也可稱為覆蓋,畢竟是把空的方法體覆蓋為具體的程式碼了。想想也是,實現介面的時候IDE是不是為我們自動加上了@Override註解?這個在JDK6之前的版本可不行,寫這個註解是會報錯的。(懷念起在老東家運維JDK1.5專案的時光)
要注意的地方:派生方法不能丟擲比基類方法範圍更廣的異常(速記:孩子不能闖比父母更大的禍),
錯誤範例:基類方法throws IOException,派生方法卻throws Exception。
派生方法不能有比基類方法更大的訪問度(速記:孩子不能比父母更能顯擺),
錯誤範例:基類方法是protected,派生方法卻是public。
隱藏Hiding
發生要素如下:
1. 同覆蓋的1.2.3.4條件(必要)
2. 僅發生在靜態方法上
要點:
隱藏不需要@Override註解修飾,加上會報錯。且派生方法的可丟擲異常範圍和可訪問範圍的約束與覆蓋相同(不能拋更多異常,不能有更廣的訪問許可權)。
在jls11文件中,隱藏註明為 by Class Methods,而覆蓋則是by Instance Methods,這個很好理解,靜態的成員方法就是屬於這個類的,隱藏也可以叫類的方法的覆蓋。
個人理解:靜態方法是和類繫結到一起的,那麼在例項化的時候,用的誰的型別的引用,那麼call到的方法就是誰的實現,也許說的不恰當,請看下例:
class Super {
static String greeting() { return "Goodnight"; }
String name() { return "Richard"; }
}
class Sub extends Super {
static String greeting() { return "Hello"; }
String name() { return "Kick"; }
}
class Test {
public static void main(String[] args) {
Super s = new Sub();
System.out.println(s.greeting() + ", " + s.name());
//輸出:Goodnight, Kick
Sub s2 = new Sub();
System.out.println(s2.greeting() + ", " + s.name());
//輸出:Hello, Kick
}
}
由於s的型別是Super,所以greeting()執行的是Super的實現,但是name()是正常的覆蓋,好比派生類沒有重寫greeting()一樣(派生類乾的事兒被藏起來了)。但是s2 call到的就是Sub的實現了,符合常規的思路。
本文參考:jsl11文件