1. 程式人生 > >【java】面向物件程式設計——類與物件的繼承和多型

【java】面向物件程式設計——類與物件的繼承和多型

一、程式碼塊

程式碼塊定義:使用 {} 定義的一段程式碼。
根據程式碼塊定義的位置以及關鍵字,又可分為以下四種:

  • 普通程式碼塊(定義在方法中,除錯)
  • 構造塊(定義在類中的(不加修飾符))
  • 靜態塊
  • 同步程式碼塊
    構造塊
    構造塊在每次產生一個新的物件就呼叫一次構造塊。
    構造塊在構造方法前執行。
    靜態塊
  1. 靜態塊優先於構造塊執行。
  2. 無論產生多少例項化物件,靜態塊都只執行一次。

靜態塊的主要作用是對static屬性進行初始化。
在主類中定義的靜態塊,優先於main執行
注:一個類的靜態塊在匯入並且使用這個類時這個靜態塊才會使用。
類中的順序


類屬性、物件屬性、靜態塊、構造塊、構造方法、靜態方法、普通方法。

外部類屬性格式:外部類名.this.屬性/方法()
注:外部類不能訪問內部類的成員屬性和方法。


二、內部類

內部類可以訪問外部類的成員屬性和方法。
訪問外部類屬性格式:

外部類名.this.屬性/方法()

外部類不能訪問內部類的成員屬性和方法。

內部類為什麼存在?
  1. 內部類方法可以訪問該類定義所在作用域中的資料,包括被 private 修飾的私有資料。
  2. 內部類可以對同一包中的其他類隱藏起來。
  3. 內部類可以實現 java 單繼承的缺陷。
  4. 當我們想要定義一個回撥函式卻不想寫大量程式碼的時候我們可以選擇使用匿名內部類來實現。
內部類與外部類的關係:
  1. 對於非靜態內部類,內部類的建立依賴外部類的例項物件,在沒有外部類例項之前是無法建立內部類的。
  2. 內部類是一個相對獨立的實體,與外部類不是is-a關係(從屬關係)。
  3. 內部類可以直接訪問外部類的元素(包含私有域),但是外部類不可以直接訪問內部類的元素。
  4. 外部類可以通過內部類引用間接訪問內部類元素。
如何例項化一個內部類的物件?

有如下兩種方法:

  1. 類名:外部類.內部類
  2. 持有一個外部類的例項化物件

如:

方法一:
Outer.Inner inner = new Outer().new Inner();

方法二:
Outer outer = new Outer(); 
Outer.Inner inner = outer.new Inner();

一個內部類建立成功後持有這個內部類所在外部類的物件。

內部類分類

成員內部類
1. 成員內部類中不能存在任何static的變數和方法
2. 成員內部類是依附於外部類的,所以只有先建立了外圍類才能夠建立內部類
靜態內部類

  1. 靜態內部類的建立是不需要依賴於外圍類,可以直接建立
  2. 靜態內部類不可以使用任何外圍類的非static成員變數和方法,而內部類則都可以要例項化一個靜態內部類的物件:
    外部類.內部類 內部類物件 = new 外部類.內部類();
    方法內部類
  3. 區域性內類不允許使用訪問許可權修飾符 public private protected 均不允許
  4. 區域性內部類對外完全隱藏,除了建立這個類的方法可以訪問它其他的地方是不允許訪問的。
  5. 區域性內部類要想使用方法形參,該形參必須用final宣告(JDK8形參變為隱式final宣告)。
    匿名內部類
  6. 匿名內部類是沒有訪問修飾符的。
  7. 匿名內部類必須繼承一個抽象類或者實現一個介面
  8. 匿名內部類中不能存在任何靜態成員或方法
  9. 匿名內部類是沒有構造方法的,因為它沒有類名。
  10. 與區域性內部相同匿名內部類也可以引用方法形參。此形參也必須宣告為 final

三、繼承的定義與使用

對類進行擴充套件,開閉原則(OCP):對外擴充套件開放,對修改關閉

  1. 單繼承
  2. 子類繼承父類所有結構(屬性、方法等),但是能不能使用,取決於訪問控制符。
  3. 如果子類和父類定義了相同的方法(覆寫),呼叫子類的用this.方法名(),呼叫父類的用super.方法名(),呼叫構造方法用super()。
  4. 子類可以例項化給父類,父類不能例項化給子類。
  5. 例項化子類物件時,先呼叫父類構造方法,再呼叫子類構造方法
  6. 如果父類裡面沒有提供無參構造方法,此時預設呼叫super();在子類的構造引數中要顯式呼叫。

在子類呼叫父類的構造方法中,有兩種方法:

(1)顯式呼叫 
	super(引數);
(2)隱式呼叫 
	super(無參);   
	this.setName(引數);

子類又被稱為派生類,父類又被稱為超類。
語法:

class 子類 extends 父類

多層繼承
層數不允許太深,最多三層。
隱式繼承
父類中都用private修飾的,子類中只能使用非private修飾的,而所有的private操作無法被直接使用,所以稱為隱式繼承。


四、覆寫

方法的覆寫

如果子類和父類定義了相同的方法名,引數列表,則子類可以對父類中的該方法進行覆寫。
注:子類覆寫的方法訪問控制權限比父類的方法更寬泛(大)。
注:

  1. 你當前使用的物件是通過哪個類new的,就用的是哪個類。
  2. 當呼叫某個方法,如果該方法已經被子類所覆寫了,那麼呼叫的一定是被覆寫過的方法。
  3. 如果在父類方法使用private定義,子類中使用public覆寫,不屬於覆寫。
    java中許可權的範圍
    public > protected > [default package] > private
過載和覆寫的區別
區別 過載(overload) 覆寫(override)
概念 方法名稱相同,引數的型別及個數不同 方法名稱、返回值型別、引數的型別及個數完全相同
範圍 一個類 繼承關係
限制 沒有許可權要求 被覆寫的方法不能擁有比父類更嚴格的訪問控制權限
屬性的覆寫

當子類定義了和父類屬性名稱完全相同的屬性的時候,就成為屬性的覆寫。
按照就近取用原則,如果子類中有就在子類中用,如果子類沒有,就去父類中找。

this和super的區別
區別 this super
概念 訪問本類中的屬性和方法 由子類訪問父類中的屬性、方法
查詢範圍 先查詢本類,如果本類沒有就呼叫父類 不查詢本類而直接呼叫父類定義
特殊 表示當前物件

五、final關鍵字

final被稱為終結器。

  1. 使用final修飾類、方法、屬性
  2. final成員變數必須在宣告的時候初始化或者在構造器中初始化,否則就會報編譯錯誤
  3. 使用final定義的類不能有子類(String類便是使用final定義)。
  4. final一旦修飾一個類之後,該類的所有方法預設都會加上final修飾。(不包含成員變數)。
  5. 使用final定義的方法不能被子類所覆寫。
  6. 使用final定義的變數就成為了常量,常量必須在宣告時賦值,並且不能夠被修改。
  7. 使用final修飾的變數不能再次賦值。
  8. 定義常量(public static final ),常量全用大寫字母,多個單詞間以_分隔。

六、多型性

方法的多型性:
  1. 方法的過載:同一個方法名稱可以根據引數的型別或個數不同調用不同的方法體
  2. 方法的覆寫:同一個父類的方法,可能根據例項化子類的不同也有不同的實現
物件的多型性:(抽象類和介面)
  1. 向上轉型:自動,父類 父類物件 = 子類例項。
  2. 向下轉型:強轉,子類 子類物件 =(子類)父類例項

向下轉型需要判斷:

物件 instanceof 型別 

返回值是boolean 如果物件是由型別例項化的但會true,否則false