Java基礎——面向物件(二)繼承
一、繼承概述
1.使用extends關鍵字
繼承後子類可以使用父類成員
2.繼承的好處
- 提高程式碼的複用性
- 讓類與類之間產生了關係,給第三個特徵多型提供了前提
3.Java中繼承的特點
Java中支援單機城。不直接支援多繼承,但對C++中的多繼承機制進行改良。
思考:為什麼Java要對多繼承機制進行改良?
這個問題也就是多繼承機制有哪些缺點?簡單來看,繼承過程中產生的多個父類中如果具有相同的成員,會產生呼叫不確定性。因此在Java中是通過“多實現”的方式來體現,即多重繼承。
當要使用一個繼承體系時:
1.檢視該體系中的頂層類,瞭解該體系的基本功能。
2.建立體系中的最子類物件,完成功能的使用。
二、定義繼承
1.什麼時候定義繼承?
當類與類之間存在著所屬關係的時候,就定義繼承。如果xxx是yyy中的一種->xxx extends yyy
2.子父類中成員變數的特點
aaa) 成員變數
- 子類中有父類的相同名稱的變數,那麼直接呼叫時呼叫的是字類中的變數。當需要區分時,用super關鍵字區分父類。
- 子類不能直接訪問父類中的私有內容(private所修飾),但可以通過get(); set();實現。
super關鍵字:super.父類成員,用法和this很相像。
和this區別:
- this代表一個本類物件的引用。
- super代表一個父類空間。
bbb) 成員函式
當子父類中成員函式一模一樣時,會執行子類的函式。這種現象稱為覆蓋操作。這是函式在子父類中的特性。當然也可以super
覆蓋:
函式有兩個特性:
- 過載,同一個類中
- 覆蓋,自類中。覆蓋也稱重寫,覆寫,override。
覆蓋的注意事項:
- 子類方法覆蓋父類方法時,子類許可權必須大於等於父類許可權——許可權只能放大
- 靜態只能覆蓋靜態,或被靜態覆蓋——同非同靜
思考:什麼時候使用覆蓋操作?
當對一個類進行子類的擴充套件時,子類需要保留父類的功能宣告,但是要定義子類中該功能的特有內容時,就使用覆蓋操作完成。
ccc) 建構函式
在子類構造物件時,發現,訪問子類建構函式時,父類也運行了,為什麼?
在子類的建構函式中第一行有一個預設的隱式語句--->super();
3.子類的例項化過程:
自類中所有的建構函式預設都會訪問父類中的空引數建構函式。
為什麼子類例項化的時候要訪問父類中的建構函式呢?
- 因為子類繼承了父類,獲取到了父類中的內容(屬性),所以在使用父類之前,要先看弗雷是如何對自己的內容進行初始化的。
- 如果父類中沒有定義空引數建構函式,那麼子類建構函式必須用super明確要呼叫父類哪個建構函式。
注意:super語句必須要定義在子類建構函式的第一行。因為父類的初始化動作要先完成。但是,如果有了this()呼叫本類建構函式,預設的super就沒有了,但是一定有一處預設呼叫super()。
一個物件例項化過程:
Person p = new Person();
- JVM會讀取指定的路徑下的Person.class檔案,並載入進記憶體,並會先加在Person的父類(如果有直接父類的情況下)。
- 在堆記憶體中開闢空間,分配地址。
- 並在物件空間中,對物件中的屬性進行預設初始化。
- 呼叫對應的建構函式進行初始化。
- 在建構函式中,第一行會先呼叫父類中建構函式進行初始化。
- 父類初始化完畢後,再對子類的屬性進行顯示初始化。
- 在進行子類建構函式的特定初始化。
- 初始化完畢後,將地址賦值給引用變數
三、final關鍵字
- final是一個修飾符,可以修飾類、方法、變數
- final修飾的類不可以被繼承。
- final修飾的方法不可以被覆蓋。
- final修飾的變數是一個常量,只能賦值一次。
思考:為什麼要用final修飾變數?
其實在程式中如果一個數據是固定的,那麼直接使用這個資料就可以了,但是這樣閱讀性差,所以給該資料起個名稱。而且這個變數名稱的值不能變化,所以加上final固定。
寫法規範:常量所有字母都大寫,多個單詞,中間用_連線。