class Grandparent { public Grandparent() { System.out.println("GrandParent Created."); } public Grandparent(String string) { System.out.println("GrandParent Created.String:" + string); } } class Parent extends Grandparent { public Parent() { super("Hello.Grandparent."); System.out.println("Parent Created"); // super("Hello.Grandparent."); } } class Child extends Parent { public Child() { System.out.println("Child Created"); } } public class TestInherits { public static void main(String args[]) { Child c = new Child(); } }
結論:通過super調用基類構造方法,必須是子類構造方法中的第一個語句。
子類必須先調用父類的構造方法是因為:
構造函數(constructor)是一種特殊的方法 。主要用來在創建對象時初始化對象, 即為對象成員變量賦初始值,總與new運算符一起使用在創建對象的語句中 。特別的一個類可以有多個構造函數 ,可根據其參數個數的不同或參數類型的不同來區分它們 即構造函數的重載。構造函數的功能主要用於在類的對象創建時定義初始化的狀態。
構造一個對象,先調用其構造方法,來初始化其成員函數和成員變量。
子類擁有父的成員變量和成員方法,如果不調用,則從父類繼承而來的成員變量和成員方法得不到正確的初始化。
不能反過來調用也是這個原因,因為父類根本不知道子類有什麼變量而且這樣一來子類也得不到初始化的父類變量,導致程序運行出錯!
不允許繼承的類:
final class 類名
{
}
以final聲明的方法不允許覆蓋。
以final聲明的變量不允許更改。
利用final,可以設計出一種特殊的"只讀"的"不可變類"。
public class ExplorationJDKSource { /** * @param args */ public static void main(String[] args) { System.out.println(new A()); } } class A{}
示例中,main方法實際上調用的是:
public void println(Object x),這一方法內部調用了String類的valueOf方法。
valueOf方法內部又調用Object.toString方法:
public String toString() {
return getClass().getName() +"@" +
Integer.toHexString(hashCode());
}
hashCode方法是本地方法,由JVM設計者實現:
public native int hashCode();
方法覆蓋:
class Parent extends Grandparent { public int add1(){ return 1; } }
class Child extends Parent { public int add1(){ return 2; } public int superadd1(){ return super.add1() ; } }
結論:方法覆蓋要求子類與父類的方法一模一樣,否則就是overload(重載)。
在子類中,若要調用父類中被覆蓋的方法,可以使用super關鍵字。
1.覆蓋的方法允許訪問范圍不能小於原方法。
2.覆蓋方法所拋出的異常不能比原方法更多。
3.聲明為final方法不允許覆蓋。 例如,object的getclass()方法不能覆蓋。
4.不能覆蓋靜態方法。
抽象類:
1.abstract修飾的類稱為“抽象類”,它只定義了什麼方法應該存在,不能創建對象,必須派生出一個子類,並在子類中實現其未實現的方法之後,才能使用new關鍵字創建對象。
在方法前加上abstract就形成抽象方法,只有方法聲明,沒有實現代碼
2.從抽象類繼承的子類必須實現父類的所有抽象方法,否則,它仍然是抽象類
3.以下模式總是成立的:
抽象類 抽象類變量 = new 派生自抽象類的具體子類();
接口:
1.定義一個接口,采用關鍵字interface,實現一個接口,采用關鍵字implements
2.接口的成員函數自動成為public的,數據成員自動成為static和final的。
3.如果接口不聲明為public的,則自動變為package。
4.一個類可以同時實現多個接口。
5.接口類型 接口類型的變量=new 實現了接口的具體類型()。
接口的擴充:
1.可以通過繼承接口來擴充已有接口,並形成一個新的接口。
interface OneInterface { void f1(); } interface TwoInterface extends OneInterface { void f2(); }
2.實現子接口的類,必須實現“父”“子”接口所定義的所有方法,才能被實例化(即new出一個對象)。
接口與抽象類的區別:
1.抽象類是一個不完全的類,而接口只是表明類應該具有哪些“外部”特征,不涉及任何實現細節。
2.接口基本上不具備繼承的任何具體特點,它僅僅承諾了外界能夠調用的方法。
3.一個類一次可以實現若干個接口,但一個類只能繼承一個父類。