6、面向對象編程(中)

  • 2021 年 6 月 17 日
  • 筆記

關鍵字:static(靜態)

作用範圍

可以用來修飾的結構:主要用來修飾類的內部結構

屬性、方法、程式碼塊、內部類

static修飾屬性:

靜態變數(或類變數)

靜態屬性 vs 非靜態屬性:

屬性,是否使用static修飾,又分為:靜態屬性 vs 非靜態屬性(實例變數)

  • 實例變數:我們創建了類的多個對象,每個對象都獨立的擁一套類中的非靜態屬性。當修改其中一個對象中的非靜態屬性時,不會導致其他對象中同樣的屬性值的修改。

  • 靜態變數:我們創建了類的多個對象,多個對象共享同一個靜態變數。當通過某一個對象修改靜態變數時,會導致其他對象調用此靜態變數時,是修改過了的。

static修飾屬性的其他說明:

① 靜態變數隨著類的載入而載入。可以通過”類.靜態變數”的方式進行調用

② 靜態變數的載入要早於對象的創建。

③ 由於類只會載入一次,則靜態變數在記憶體中也只會存在一份:存在方法區的靜態域中

記憶體解析:

untitle.png

static修飾方法:

① 隨著類的載入而載入,可以通過”類.靜態方法”的方式進行調用

② 靜態方法中,只能調用靜態的方法或屬性

 非靜態方法中,既可以調用非靜態的方法或屬性,也可以調用靜態的方法或屬性

static修飾程式碼塊:

靜態程式碼塊:

>內部可以輸出語句

>隨著類的載入而執行,而且只執行一次

>作用:初始化類的資訊

>如果一個類中定義了多個靜態程式碼塊,則按照聲明的先後順序執行

>靜態程式碼塊的執行要優先於非靜態程式碼塊的執行

>靜態程式碼塊內只能調用靜態的屬性、靜態的方法,不能調用非靜態的結構

非靜態程式碼塊:

>內部可以輸出語句

>隨著對象的創建而執行

>每創建一個對象,就執行一次非靜態程式碼塊

>作用:可以在創建對象時,對對象的屬性等進行初始化

>如果一個類中定義了多個非靜態程式碼塊,則按照聲明的先後順序執行

>非靜態程式碼塊內可以調用靜態的屬性、靜態的方法,或非靜態的屬性、非靜態的方法

static的注意點:

在靜態的方法內,不能使用this關鍵字、super關鍵字

什麼時候使用static

屬性:

  • 屬性是可以被多個對象所共享的,不會隨著對象的不同而不同的。

  • 類中的常量也常常聲明為static

方法:

  • 操作靜態屬性的方法,通常設置為static的

  • 工具類中的方法,習慣上聲明為static的。 比如:Math、Arrays、Collections

main方法

  1. 作為程式的入口出現

  2. main()方法也是一個普通的靜態方法

  3. main()方法可以作為我們與控制台交互的方式。(之前:使用Scanner)

面向對象特徵二:繼承性

extends:延展、擴展

格式:

class A extends B{}

  • A:子類、派生類、subclass

  • B:父類、超類、基類、superclass

子類繼承父類以後有哪些不同?

  • 體現:一旦子類A繼承父類B以後,子類A中就獲取了父類B中聲明的所有的屬性和方法。

  • 特別的,父類中聲明為private的屬性或方法,子類繼承父類以後,仍然認為獲取了父類中私有的結構。只因為封裝性的影響,使得子類不能直接調用父類的結構而已。

  • 子類繼承父類以後,還可以聲明自己特有的屬性或方法:實現功能的拓展。

  • 子類和父類的關係,不同於子集和集合的關係。

Java中繼承性的說明

  1. 一個類可以被多個子類繼承。

  2. Java中類的單繼承性:一個類只能有一個父類

  3. 子父類是相對的概念。

  4. 子類直接繼承的父類,稱為:直接父類。間接繼承的父類稱為:間接父類

  5. 子類繼承父類以後,就獲取了直接父類以及所間接父類中聲明的屬性和方法

方法重寫:

override 或 overwrite

子類繼承父類以後,可以對父類中同名同參數的方法,進行覆蓋操作

重寫以後,當創建子類對象以後,通過子類對象調用子父類中的同名同參數的方法時,實際執行的是子類重寫父類的方法。

例如

class Circle{
	public double findArea(){}//求面積
}
class Cylinder extends Circle{
	public double findArea(){}//求表面積
}
**************************************
class Account{
	public boolean withdraw(double amt){}
}
class CheckAccount extends Account{
	public boolean withdraw(double amt){}
}

重寫的規則:

許可權修飾符  返回值類型  方法名(形參列表)  throws  異常的類型{

                  //方法體

}

約定俗稱:子類中的叫重寫的方法,父類中的叫被重寫的方法

① 子類重寫的方法的方法名和形參列表與父類被重寫的方法的方法名和形參列表相同

② 子類重寫的方法的許可權修飾符不小於父類被重寫的方法的許可權修飾符

  • 特殊情況:子類不能重寫父類中聲明為private、static、final的方法

③ 返回值類型:

  • 父類被重寫的方法的返回值類型是void,則子類重寫的方法的返回值類型只能是void

  • 父類被重寫的方法的返回值類型是A類型,則子類重寫的方法的返回值類型可以是A類或A類的子類

  • 父類被重寫的方法的返回值類型是基本數據類型(比如:double),則子類重寫的方法的返回值類型必須是相同的基本數據類型(必須也是double)

④ 子類重寫的方法拋出的異常類型不大於父類被重寫的方法拋出的異常類型

super關鍵字

super 關鍵字可以理解為:父類的

可以用來調用的結構:屬性、方法、構造器

super調用屬性、方法:

  • 我們可以在子類的方法或構造器中。通過使用”super.屬性”或”super.方法”的方式,顯式的調用父類中聲明的屬性或方法。但是,通常情況下,我們習慣省略”super.”

  • 特殊情況:當子類和父類中定義了同名的屬性時,我們要想在子類中調用父類中聲明的屬性,則必須顯式的使用”super.屬性”的方式,表明調用的是父類中聲明的屬性。

  • 特殊情況:當子類重寫了父類中的方法以後,我們想在子類的方法中調用父類中被重寫的方法時,則必須顯式的使用”super.方法”的方式,表明調用的是父類中被重寫的方法。

super調用構造器:

  • 我們可以在子類的構造器中顯式的使用”super(形參列表)”的方式,調用父類中聲明的指定的構造器

  • “super(形參列表)”的使用,必須聲明在子類構造器的首行!

  • 我們在類的構造器中,針對於”this(形參列表)”或”super(形參列表)”只能二一,不能同時出現

  • 在構造器的首行,沒顯式的聲明”this(形參列表)”或”super(形參列表)”,則默認調用的是父類中空參的構造器:super()

  • 在類的多個構造器中,至少一個類的構造器中使用了”super(形參列表)”,調用父類中的構造器

類的初始化順序:

  1. 載入父類(給父類的靜態屬性開闢空間、賦默認值、賦初始值,執行靜態塊)

  2. 載入子類(給子類的靜態屬性開闢空間、賦默認值、賦初始值,執行靜態塊)

以下是在創建子類對象的時候才會發生:

  1. 對父類中定義的非靜態屬性分配空間,賦默認值,做初始化(執行父類中定義的初始化塊,執行父類的構造方法)

注意:默認執行的是父類的無參數的構造方法,如果在子類中使用super顯示的調用了父類的其他構造方法,無參的就不會再次被調用

  1. 對子類中定義的非靜態屬性進行初始化(執行子類中定義的初始化塊,執行子類中定義的構造方法,創建子類對象)

關鍵字:abstract(抽象的)

可以用來修飾:類、方法

不可以和private、static、final、一起使用,不可以修飾構造器

abstract修飾類:抽象類

  • 此類不能實例化

  • 抽象類中一定有構造器,便於子類實例化時調用(涉及:子類對象實例化的全過程)

  • 開發中,都會提供抽象類的子類,讓子類對象實例化,完成相關的操作
    —>抽象的使用前提:繼承性

abstract修飾方法:抽象方法

  • 抽象方法只方法的聲明,沒方法體

  • 包含抽象方法的類,一定是一個抽象類。反之,抽象類中可以沒有抽象方法的。

  • 若子類重寫了父類中的所的抽象方法後,此子類方可實例化

  • 若子類沒重寫父類中的所的抽象方法,則此子類也是一個抽象類,需要使用abstract修飾

面向對象特徵三:多態性

可以理解為一個事物的多種形態。

對象的多態性:父類的引用指向子類的對象(或子類的對象賦給父類的引用)

多態性的使用:虛擬方法調用

  • 有了對象的多態性以後,我們在編譯期,只能調用父類中聲明的方法,但在運行期,我們實際執行的是子類重寫父類的方法。

  • 總結:編譯,看左邊;運行,看右邊。

對象的多態性,只適用於方法,不適用於屬性(編譯和運行都看左邊)

向上轉型:

多態性

向下轉型:

為什麼使用向下轉型:

  • 有了對象的多態性以後,記憶體中實際上是載入了子類特有的屬性和方法的,但是由於變數聲明為父類類型,導致編譯時,只能調用父類中聲明的屬性和方法。子類特有的屬性和方法不能調用。如何才能調用子類特的屬性和方法?使用向下轉型。

如何實現向下轉型:

  • 使用強制類型轉換符:()

使用時的注意點:

  • 使用強轉時,可能出現ClassCastException的異常。

  • 為了避免在向下轉型時出現ClassCastException的異常,我們在向下轉型之前,先進行instanceof的判斷,一旦返回true,就進行向下轉型。如果返回false,不進行向下轉型。

instanceof 的使用:

  • a instanceof A :
    判斷對象a是否是類A的實例。如果是,返回true;如果不是,返回false。

  • 類B是類A的父類:a instanceof A返回true,a instanceof B也返回true