【小白轉碼】06
一、封裝 encapsulation
1.遵循的原則
隨著我們系統越來越複雜,類會越來越多,那麼類之間的訪問邊界必須把握好,面向物件的開發原則要遵循“高內聚、低耦合”,而“高內聚,低耦合”的體現之一:
-
高內聚:類的內部資料操作細節自己完成,不允許外部干涉;
-
低耦合:僅對外暴露少量的方法用於使用
通俗的講,封裝就是把該隱藏的隱藏起來,該暴露的暴露出來。
2.許可權修飾符
許可權修飾符共有4種,分別為public,protected、預設、private;許可權修飾符可以使得資料在一定範圍內可見或者隱藏。
修飾符 | 本類 | 本包 | 其他包子類 | 任意位置 |
---|---|---|---|---|
private | √ |
× | × | × |
預設 | √ | √ | × | × |
protected | √ | √ | √ | × |
public | √ | √ | √ | √ |
許可權修飾符可以修飾:
外部類:public和預設
成員變數、成員方法、構造器、成員內部類:public,protected,預設,private
3.類的封裝
-
類的封裝的意義:
-
隱藏類的實現細節
-
- 讓使用者只能通過事先預定的方法來訪問資料,從而可以在該方法裡面加入控制邏輯,限制對成員變數的不合理訪問。還可以進行資料檢查,從而有利於保證物件資訊的完整性。
- 便於修改,提高程式碼的可維護性。主要說的是隱藏的部分,在內部修改了,如果其對外可以的訪問方式不變的話,外部根本感覺不到它的修改。例如:Java8->Java9,String從char[]轉為byte[]內部實現,而對外的方法不變,我們使用者根本感覺不到它內部的修改。
-
如何進行類的封裝?
-
成員變數(field)私有化
-
提供標準的get/set方法
-
二、基礎 inherit
1.Java中的繼承
Java中有父類、子類的概念,類似生活中的父子關係,父類中的一些屬性和方法可以被子類繼承下來使用,不再需要重複定義。
2.繼承的特點
2.2 子類無法直接使用父類的私有成員
2.3 Java只支援單繼承
2.4 Java支援多層繼承
2.5 一個類可以同時擁有多個子類
3.方法的重寫 override
當子類繼承了父類的某個方法之後,發現這個方法並不能滿足子類的實際需求,那麼可以通過方法重寫,覆蓋父類的方法。
3.1 方法重寫:
子類中定義與父類中相同的方法,一般方法體不同,用於改造並覆蓋父類的方法。
3.2 方法重寫的具體要求:
-
必須保證父子類之間重寫方法的名稱相同。
-
必須保證父子類之間重寫方法的引數列表也完全相同。
-
子類方法的返回值型別必須【小於等於】父類方法的返回值型別(小於其實就是是它的子類,例如:Cat< Animal)。
注意:如果返回值型別是基本資料型別和void,那麼必須是相同
-
子類方法的許可權必須【大於等於】父類方法的許可權修飾符。
注意:public > protected > 預設 > private
父類私有方法不能重寫
跨包的父類預設的方法也不能重寫
另外:
靜態方法不能被重寫,方法重寫指的是例項方法重寫,靜態方法屬於類的方法不能被重寫,而是隱藏。
final修飾的方法不能被重寫
父類private方法不能重寫
三、多型polymorphism
1.多型的形式
Java規定父類型別的變數可以接收子類型別的物件,這一點從邏輯上也是說得通的。
父類型別 變數名 = 子類物件;
父類型別:指子類繼承的父類型別,或者實現的父介面型別。
所以說繼承是多型的前提
//多型的引用形式
Animal a = new Cat();//Cat物件也屬於其父類Animal型別。貓也是一個動物。
2.多型的表現
多型引用形式的具體表現:編譯時型別與執行時型別不一致,編譯時看左邊的“父類”,執行時看右邊的“子類”。
也就是我們常說的:編譯看左邊,執行看右邊。
3.多型的好處
執行時,看“子類”,如果子類重寫了方法,一定是執行子類重寫的方法;變數引用的子類物件不同,執行的方法就不同,實現動態繫結。程式碼編寫更靈活、功能更強大,可維護性和擴充套件性更好了。
-
提高程式的擴充套件性(參考引入案例分析)
-
降低類與類之間的耦合度(參考引入案例分析)
4.向上轉型與向下轉型
首先,一個物件在new的時候建立是哪個型別的物件,它從頭至尾都不會變。即這個物件的執行時型別,本質的型別用於不會變。但是,把這個物件賦值給不同型別的變數時,這些變數的編譯時型別卻不同。
這個和基本資料型別的轉換是不同的。基本資料型別是把資料值copy了一份,相當於有兩種資料型別的值。而物件的賦值不會產生兩個物件。
1、為什麼要型別轉換呢?
因為多型,就一定會有把子類物件賦值給父類變數的時候,這個時候,在編譯期間,就會出現型別轉換的現象。
但是,使用父類變數接收了子類物件之後,我們就不能呼叫子類擁有,而父類沒有的方法了。這也是多型給我們帶來的一點"小麻煩"。所以,想要呼叫子類特有的方法,必須做型別轉換,使得編譯通過。
-
向上轉型:當左邊的變數的型別(父類) > 右邊物件/變數的型別(子類),我們就稱為向上轉型
-
此時,編譯時按照左邊變數的型別處理,就只能呼叫父類中有的變數和方法,不能呼叫子類特有的變數和方法了
-
但是,執行時,仍然是物件本身的型別,所以執行的方法是子類重寫的方法體。
-
此時,一定是安全的,而且也是自動完成的
-
-
向下轉型:當左邊的變數的型別(子類)<右邊物件/變數的編譯時型別(父類),我們就稱為向下轉型
-
此時,編譯時按照左邊變數的型別處理,就可以呼叫子類特有的變數和方法了
-
但是,執行時,仍然是物件本身的型別
-
不是所有通過編譯的向下轉型都是正確的,可能會發生ClassCastException,為了安全,可以通過isInstanceof關鍵字進行判斷
-
5.如何向上轉型與向下轉型
向上轉型:自動完成
向下轉型:(子類型別)父類變數
6.instanceof關鍵字
instanceof
關鍵字用於判斷一個物件的執行時型別
為了避免ClassCastException
的發生,Java提供了 instanceof
關鍵字,給引用變數做型別的校驗,只要用instanceof
判斷返回true的,那麼強轉為該型別就一定是安全的,不會報ClassCastException
異常。
格式:
變數/匿名物件 instanceof 資料型別
那麼,哪些instanceof
判斷會返回true呢?
-
變數/匿名物件的編譯時型別 與
instanceof
後面資料型別是直系親屬關係才可以比較 -
變數/匿名物件的執行時型別<= instanceof後面資料型別,才為true
一、封裝 encapsulation
1.遵循的原則
隨著我們系統越來越複雜,類會越來越多,那麼類之間的訪問邊界必須把握好,面向物件的開發原則要遵循“高內聚、低耦合”,而“高內聚,低耦合”的體現之一:
-
高內聚:類的內部資料操作細節自己完成,不允許外部干涉;
-
低耦合:僅對外暴露少量的方法用於使用
通俗的講,封裝就是把該隱藏的隱藏起來,該暴露的暴露出來。
2.許可權修飾符
許可權修飾符共有4種,分別為public,protected、預設、private;許可權修飾符可以使得資料在一定範圍內可見或者隱藏。
修飾符 | 本類 | 本包 | 其他包子類 | 任意位置 |
---|---|---|---|---|
private | √ | × | × | × |
預設 | √ | √ | × | × |
protected | √ | √ | √ | × |
public | √ | √ | √ | √ |
許可權修飾符可以修飾:
外部類:public和預設
成員變數、成員方法、構造器、成員內部類:public,protected,預設,private
3.類的封裝
-
類的封裝的意義:
-
隱藏類的實現細節
-
- 讓使用者只能通過事先預定的方法來訪問資料,從而可以在該方法裡面加入控制邏輯,限制對成員變數的不合理訪問。還可以進行資料檢查,從而有利於保證物件資訊的完整性。
- 便於修改,提高程式碼的可維護性。主要說的是隱藏的部分,在內部修改了,如果其對外可以的訪問方式不變的話,外部根本感覺不到它的修改。例如:Java8->Java9,String從char[]轉為byte[]內部實現,而對外的方法不變,我們使用者根本感覺不到它內部的修改。
-
如何進行類的封裝?
-
成員變數(field)私有化
-
提供標準的get/set方法
-
二、基礎 inherit
1.Java中的繼承
Java中有父類、子類的概念,類似生活中的父子關係,父類中的一些屬性和方法可以被子類繼承下來使用,不再需要重複定義。
2.繼承的特點
2.2 子類無法直接使用父類的私有成員
2.3 Java只支援單繼承
2.4 Java支援多層繼承
2.5 一個類可以同時擁有多個子類
3.方法的重寫 override
當子類繼承了父類的某個方法之後,發現這個方法並不能滿足子類的實際需求,那麼可以通過方法重寫,覆蓋父類的方法。
3.1 方法重寫:
子類中定義與父類中相同的方法,一般方法體不同,用於改造並覆蓋父類的方法。
3.2 方法重寫的具體要求:
-
必須保證父子類之間重寫方法的名稱相同。
-
必須保證父子類之間重寫方法的引數列表也完全相同。
-
子類方法的返回值型別必須【小於等於】父類方法的返回值型別(小於其實就是是它的子類,例如:Cat< Animal)。
注意:如果返回值型別是基本資料型別和void,那麼必須是相同
-
子類方法的許可權必須【大於等於】父類方法的許可權修飾符。
注意:public > protected > 預設 > private
父類私有方法不能重寫
跨包的父類預設的方法也不能重寫
另外:
靜態方法不能被重寫,方法重寫指的是例項方法重寫,靜態方法屬於類的方法不能被重寫,而是隱藏。
final修飾的方法不能被重寫
父類private方法不能重寫
三、多型polymorphism
1.多型的形式
Java規定父類型別的變數可以接收子類型別的物件,這一點從邏輯上也是說得通的。
父類型別 變數名 = 子類物件;
父類型別:指子類繼承的父類型別,或者實現的父介面型別。
所以說繼承是多型的前提
//多型的引用形式
Animal a = new Cat();//Cat物件也屬於其父類Animal型別。貓也是一個動物。
2.多型的表現
多型引用形式的具體表現:編譯時型別與執行時型別不一致,編譯時看左邊的“父類”,執行時看右邊的“子類”。
也就是我們常說的:編譯看左邊,執行看右邊。
3.多型的好處
執行時,看“子類”,如果子類重寫了方法,一定是執行子類重寫的方法;變數引用的子類物件不同,執行的方法就不同,實現動態繫結。程式碼編寫更靈活、功能更強大,可維護性和擴充套件性更好了。
-
提高程式的擴充套件性(參考引入案例分析)
-
降低類與類之間的耦合度(參考引入案例分析)
4.向上轉型與向下轉型
首先,一個物件在new的時候建立是哪個型別的物件,它從頭至尾都不會變。即這個物件的執行時型別,本質的型別用於不會變。但是,把這個物件賦值給不同型別的變數時,這些變數的編譯時型別卻不同。
這個和基本資料型別的轉換是不同的。基本資料型別是把資料值copy了一份,相當於有兩種資料型別的值。而物件的賦值不會產生兩個物件。
1、為什麼要型別轉換呢?
因為多型,就一定會有把子類物件賦值給父類變數的時候,這個時候,在編譯期間,就會出現型別轉換的現象。
但是,使用父類變數接收了子類物件之後,我們就不能呼叫子類擁有,而父類沒有的方法了。這也是多型給我們帶來的一點"小麻煩"。所以,想要呼叫子類特有的方法,必須做型別轉換,使得編譯通過。
-
向上轉型:當左邊的變數的型別(父類) > 右邊物件/變數的型別(子類),我們就稱為向上轉型
-
此時,編譯時按照左邊變數的型別處理,就只能呼叫父類中有的變數和方法,不能呼叫子類特有的變數和方法了
-
但是,執行時,仍然是物件本身的型別,所以執行的方法是子類重寫的方法體。
-
此時,一定是安全的,而且也是自動完成的
-
-
向下轉型:當左邊的變數的型別(子類)<右邊物件/變數的編譯時型別(父類),我們就稱為向下轉型
-
此時,編譯時按照左邊變數的型別處理,就可以呼叫子類特有的變數和方法了
-
但是,執行時,仍然是物件本身的型別
-
不是所有通過編譯的向下轉型都是正確的,可能會發生ClassCastException,為了安全,可以通過isInstanceof關鍵字進行判斷
-
5.如何向上轉型與向下轉型
向上轉型:自動完成
向下轉型:(子類型別)父類變數
6.instanceof關鍵字
instanceof
關鍵字用於判斷一個物件的執行時型別
為了避免ClassCastException
的發生,Java提供了 instanceof
關鍵字,給引用變數做型別的校驗,只要用instanceof
判斷返回true的,那麼強轉為該型別就一定是安全的,不會報ClassCastException
異常。
格式:
變數/匿名物件 instanceof 資料型別
那麼,哪些instanceof
判斷會返回true呢?
-
變數/匿名物件的編譯時型別 與
instanceof
後面資料型別是直系親屬關係才可以比較 -
變數/匿名物件的執行時型別<= instanceof後面資料型別,才為true