java 對象實例化過程中的多態特性解析

java 對象實例化過程中的多態特性

執行對象實例化過程中遵循多態特性 ==> 調用的方法都是實例化的子類中的重寫方法,隻有明確調用瞭super.xxx關鍵詞或者是子類中沒有該方法時,才會去調用父類相同的同名方法。

通過案例說明

package com.njau.test1; 
class Test {
    public static void main(String[] args) {
        System.out.println(new B().getValue());
    }
    static class A {
        protected int value;
        public A (int v) {
            setValue(v);
        }
        public void setValue(int value) {
            this.value= value;
        }
        public int getValue() {
            try {
                value ++;
                return value;
            } finally {
                this.setValue(value);
                System.out.println(value);
            }
        }
    }
    static class B extends A {
        public B () {
            super(5);
            setValue(getValue()- 3);
        }
        public void setValue(int value) {
            super.setValue(2 * value);
        }
    }
}

通過上述代碼

始終明確調用的方法必須是實例化子類中重寫的方法。

首先,在main函數中,【new B()】new瞭一個B類的實例化對象,在實例化對象時,調用瞭B類中的構造函數,執行【super(5)】,也就是public A(int v)——>setValue(v),由於調用的方法必須是實例化子類中重寫的方法的原則。因此,這裡調用的是B類中的setValue(v)方法,此時B實例的value值設置為2 x 5 = 10,後執行super.setValue(10),將value=10的值存儲起來。

執行完super(5)後,執行構造函數中的【setValue(getValue()- 3)】中【getValue()】,由於B類中沒有getValue()方法,則調用父類(A類)中的getValue()方法,value++所得到的值為11,並存儲在value中(先執行finally中的部分,後執行try中的return),在finally中,調用瞭【this.setValue(value)】,由於調用的方法必須是實例化子類中重寫的方法的原則,調用的是B類中的setValue(v)方法,此時B實例的value值設置為2 x 11= 22,之後執行System.out.println(value)

即在控制臺上打印22

執行完finally中的部分,後執行try中的return,將value++執行後,存儲在value中的11,return回去;執行【setValue(getValue()- 3)】,即:setValue(8)

執行setValue(8)時,由於調用的方法必須是實例化子類中重寫的方法的原則,則調用B類中的setValue(v)方法,此時B實例的value值設置為2 x 8= 16;此時B類中的構造函數執行結束。

在實例化對象以後,執行【new B().getValue()】,由於B類中沒有getValue()方法,則調用父類(A類)中的getValue()方法,value++所得到的值為17,並存儲在value中,在finally中,調用瞭【this.setValue(value)】,由於調用的方法必須是實例化子類中重寫的方法的原則,調用的是B類中的setValue(v)方法,此時B實例的value值設置為2 x 17= 34,之後執行System.out.println(value)

即在控制臺上打印34

執行完finally中的部分,後執行try中的return,將value++執行後,存儲在value中的17,return回去;執行【System.out.println(new B().getValue())】

即在控制臺上打印17

value值的變化過程,僅解釋實例化對象時,構造函數中:super(5)與setValue(getValue()+3)兩部分。圖中兩條線,起點分別為【new B()】與【setValue(getValue()+3)】:

執行結果為:

java對象的三個特性(封裝、繼承、多態)

類(類型)和對象:對象是獨一無二的。對象有其所屬之類型。對象是類型的一個具體的實例。

創建編寫一個 class :定義一個類型。類型是編寫出來的,即使程序不運行,類型已然存在。

對象:對象是new出來的,在程序運行期間new出來的,存在於內存中(堆中 )。如果程序未運行,則對象不存在。

對象的三大特性:

1.封裝

1.1 把本屬於某個類型的成員屬性(靜態特性)和職責(動態特性)定義到一個類中。

1.2 訪問權限控制:使用權限訪問修飾符控制成員(屬性和方法)的訪問(可見性)。

  • private:最小訪問權限,僅限類的內部可以訪問。
  • <無修飾符>:包修飾符,友好訪問修飾符,類內,包內可以訪問。
  • protected:類內,包內,子類可以訪問。
  • public:類內,包內,子類,包外都可以訪問。

類的兩大成員:

1.屬性:有默認值,0 0.0 false ‘\0’ null。引用類型的默認值是null值。

2.方法:方法中,可以訪問成員屬性。

構造方法:

用於構造對象(對對象進行成員屬性初始化),構造對象的過程可能簡單,也可能復雜。

  • 和類同名。語法:new 構造方法(參數列表)
  • 無返回值。其作用僅為構造對象。
  • 構造方法可以重載。

this關鍵字:

  • 訪問當前對象的屬性和方法。
  • this(參數列表),隻能放在構造方法的第一行,並且隻能單獨使用。
  • 當方法的參數和成員屬性名稱沖突的時候,可以使用this進行區分。

2.繼承

2.1 為什麼要繼承:消除重復。子類可以繼承父類的某些成員。

2.2 extends 關鍵字:擴展。一個類隻能繼承一個父類。如果沒有指定父類的話,則默認繼承自Object類。Object類是根類型,終級類,沒有父類。其它一切引用類型都是直接或間接繼承自Object類型。

2.3 什麼成員可以被繼承?1. 私有成員不能被繼承。2. 構造方法不能被繼承。

2.4 子類對象構造的過程:按照繼承的順序,遞歸創建各類型的狀態值。

3.多態

同一個類型所展現出的行為或屬性的多種形態。

使用父類(祖先類、接口)的引用指向子類(派生類,實現類)的對象。

多態的使用場景:某些場景,隻希望關註某些(不同的具體類型)類型的共性(祖先類,接口),而忽略其它獨特的特性。

final:

  • 修飾類,表示類不可被繼承。
  • 修飾方法,表示方法不能被重寫。
  • 修飾成員屬性,或者普通變量,表示值不可修改。

static:靜態的

  • 一旦屬性和方法,添加瞭static關鍵字,表示屬性和方法是屬於類的,而不是屬於某一個具體的對象的。
  • 通過“類名.靜態成員”來訪問,而無須先創建對象。

抽象類:

  • 當定義一個類時,如果某個方法暫時不便實現,或者無法實現,或者不適合實現,或者希望具體的子類來提供實現,可以使用abstract關鍵字來修飾此方法,表示抽象方法,抽象方法無需提供實現。
  • 當一個類中存在抽象方法時,類必須定義成抽象類。但是,一個抽象類中可以沒有抽象方法。
  • 抽象類不能實例化,但可以定義構造方法。
  • 抽象類是類,擁有一切類的特性,除瞭不能實例化。

接口:

  • 接口不是類。但是接口和抽象類類似。
  • 接口中的方法全都是公有的抽象方法。jdk8之前。
  • 接口中的屬性,都是公有的靜態的最終的。
  • 接口需要類來提供實現。implements關鍵字。一個類可以實現多個接口,相當於將所有這些接口的方法提供實現。
  • 接口可以繼承接口,使用 extends 關鍵字。
  • 接口也可以使用多態特性,使用接口的引用指向實現類的實例。
  • 接口的主要目的(作用)就是多態。

以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。

推薦閱讀: