国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【JavaSE】面向?qū)ο缶幊趟枷胫鄳B(tài)(圖文詳解)

這篇具有很好參考價值的文章主要介紹了【JavaSE】面向?qū)ο缶幊趟枷胫鄳B(tài)(圖文詳解)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

【JavaSE】面向?qū)ο缶幊趟枷胫鄳B(tài)(圖文詳解),JavaSE,java,開發(fā)語言,ide,學(xué)習(xí)方法

目錄

1.?多態(tài)的概念

2. 多態(tài)實現(xiàn)條件

3. 重寫

4. 向上轉(zhuǎn)型和向下轉(zhuǎn)型

4.1 向上轉(zhuǎn)型

4.2 向下轉(zhuǎn)型

5. 多態(tài)的優(yōu)缺點

6. 避免在構(gòu)造方法中調(diào)用重寫的方法


1.?多態(tài)的概念

多態(tài)的概念:通俗來說,就是多種形態(tài),具體點就是去完成某個行為,當(dāng)不同的對象去完成時會產(chǎn)生出不同的狀態(tài)。

【JavaSE】面向?qū)ο缶幊趟枷胫鄳B(tài)(圖文詳解),JavaSE,java,開發(fā)語言,ide,學(xué)習(xí)方法

?總的來說:同一件事情,發(fā)生在不同對象身上,就會產(chǎn)生不同的結(jié)果。

2. 多態(tài)實現(xiàn)條件

在java中要實現(xiàn)多態(tài),必須要滿足如下幾個條件,缺一不可:

1. 必須在繼承體系下

2. 子類必須要對父類中方法進行重寫

3. 通過父類的引用調(diào)用重寫的方法

多態(tài)體現(xiàn):在代碼運行時,當(dāng)傳遞不同類對象時,會調(diào)用對應(yīng)類中的方法。?

下面是一個多態(tài)的示例:

class Animal {
    public void makeSound() {
        System.out.println("動物發(fā)出聲音");
    }
}

class Cat extends Animal {
    @Override
    public void makeSound() {
        System.out.println("貓發(fā)出喵喵的聲音");
    }
}

class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("狗發(fā)出汪汪的聲音");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal animal1 = new Cat();
        Animal animal2 = new Dog();

        animal1.makeSound(); // 輸出:貓發(fā)出喵喵的聲音
        animal2.makeSound(); // 輸出:狗發(fā)出汪汪的聲音
    }
}

3. 重寫

引入:

在閱讀下面代碼之前,建議先學(xué)習(xí)向上轉(zhuǎn)型。

class Animal {
    String name;
    int age;
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public void eat() {
        System.out.println(name + "吃飯");
    }
}
class Dog extends Animal {
    public Dog(String name, int age) {
        super(name, age);
    }
}
public class Test {
    public static void main(String[] args) {
        Animal animal = new Dog("小狗",2);
        animal.eat();
    }
}

?對于上面的代碼,我們可以輕松的看出程序?qū)蛴〉膬?nèi)容:

【JavaSE】面向?qū)ο缶幊趟枷胫鄳B(tài)(圖文詳解),JavaSE,java,開發(fā)語言,ide,學(xué)習(xí)方法

?但是,如果在Dog這個類中也有eat()這個方法,程序會輸出什么樣的結(jié)果呢:

class Animal {
    String name;
    int age;
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public void eat() {
        System.out.println(name + "吃飯");
    }
}
class Dog extends Animal {
    public Dog(String name, int age) {
        super(name, age);
    }
    public void eat() {
        System.out.println(name + "吃骨頭~~");
    }
}
public class Test {
    public static void main(String[] args) {
        Animal animal = new Dog("小狗", 2);
        animal.eat();
    }
}

這時我們發(fā)現(xiàn),程序輸出結(jié)果:

【JavaSE】面向?qū)ο缶幊趟枷胫鄳B(tài)(圖文詳解),JavaSE,java,開發(fā)語言,ide,學(xué)習(xí)方法

?此時的你是不是也在想,為什么輸出的不是父類的eat方法呢?這里就要講到重寫了:

重寫(override):也稱為覆蓋。重寫是子類對父類非靜態(tài)、非private修飾,非final修飾,非構(gòu)造方法等的實現(xiàn)過程進行重新編寫, 返回值和形參都不能改變。即外殼不變,核心重寫!重寫的好處在于子類可以根據(jù)需要,定義特定于自己的行為。 也就是說子類能夠根據(jù)需要實現(xiàn)父類的方法。

以上面代碼為例:【JavaSE】面向?qū)ο缶幊趟枷胫鄳B(tài)(圖文詳解),JavaSE,java,開發(fā)語言,ide,學(xué)習(xí)方法

?此時通過父類的引用調(diào)用的是子類的eat()方法,我們把這個過程稱為動態(tài)綁定。

【方法重寫的規(guī)則】

  1. 子類在重寫父類的方法時,一般必須與父類方法原型一致: 返回值類型方法名 (參數(shù)列表) 要完全一致
  2. 被重寫的方法返回值類型可以不同,但是必須是具有父子關(guān)系的
  3. 訪問權(quán)限不能比父類中被重寫的方法的訪問權(quán)限更低。例如:如果父類方法被public修飾,則子類中重寫該方法就不能聲明為 protected.訪問權(quán)限:private < default < protected <public
  4. 父類被static、private修飾的方法、構(gòu)造方法都不能被重寫。
  5. 重寫的方法, 可以使用 @Override 注解來顯式指定. 有了這個注解能幫我們進行一些合法性校驗. 例如不小心將方法名字拼寫錯了 (比如寫成 aet), 那么此時編譯器就會發(fā)現(xiàn)父類中沒有 aet 方法, 就會編譯報錯, 提示無法構(gòu)成重寫.

對于第3種情況的代碼示意:

【JavaSE】面向?qū)ο缶幊趟枷胫鄳B(tài)(圖文詳解),JavaSE,java,開發(fā)語言,ide,學(xué)習(xí)方法

?文章來源地址http://www.zghlxwxcb.cn/news/detail-628885.html

?【重寫和重載的區(qū)別】

【JavaSE】面向?qū)ο缶幊趟枷胫鄳B(tài)(圖文詳解),JavaSE,java,開發(fā)語言,ide,學(xué)習(xí)方法

?即:方法重載是一個類的多態(tài)性表現(xiàn),而方法重寫是子類與父類的一種多態(tài)性表現(xiàn)。

【JavaSE】面向?qū)ο缶幊趟枷胫鄳B(tài)(圖文詳解),JavaSE,java,開發(fā)語言,ide,學(xué)習(xí)方法

?

【重寫的設(shè)計原則】

對于已經(jīng)投入使用的類,盡量不要進行修改。最好的方式是:重新定義一個新的類,來重復(fù)利用其中共性的內(nèi)容, 并且添加或者改動新的內(nèi)容。

例如:若干年前的手機,只能打電話,發(fā)短信,來電顯示只能顯示號碼,而今天的手機在來電顯示的時候,不僅僅可以顯示號碼,還可以顯示頭像,地區(qū)等。在這個過程當(dāng)中,我們不應(yīng)該在原來老的類上進行修改,因為原來的類,可能還在有用戶使用,正確做法是:新建一個新手機的類,對來電顯示這個方法重寫就好了,這樣就達到了我們當(dāng)今的需求了。

【JavaSE】面向?qū)ο缶幊趟枷胫鄳B(tài)(圖文詳解),JavaSE,java,開發(fā)語言,ide,學(xué)習(xí)方法

靜態(tài)綁定:也稱為前期綁定(早綁定),即在編譯時,根據(jù)用戶所傳遞實參類型就確定了具體調(diào)用那個方法。典型代表函數(shù)重載。

動態(tài)綁定:也稱為后期綁定(晚綁定),即在編譯時,不能確定方法的行為,需要等到程序運行時,才能夠確定具體調(diào)用那個類的方法。

4. 向上轉(zhuǎn)型和向下轉(zhuǎn)型

4.1 向上轉(zhuǎn)型

向上轉(zhuǎn)型:實際就是創(chuàng)建一個子類對象,將其當(dāng)成父類對象來使用。

語法格式父類類型 對象名 = new 子類類型()

舉個“栗”子:

【JavaSE】面向?qū)ο缶幊趟枷胫鄳B(tài)(圖文詳解),JavaSE,java,開發(fā)語言,ide,學(xué)習(xí)方法

?animal是父類類型,但可以引用一個子類對象,因為是從小范圍向大范圍的轉(zhuǎn)換。

?【使用場景】

1. 直接賦值

直接賦值:子類對象賦值給父類對象

【JavaSE】面向?qū)ο缶幊趟枷胫鄳B(tài)(圖文詳解),JavaSE,java,開發(fā)語言,ide,學(xué)習(xí)方法

2. 方法傳參

方法傳參:形參為父類型引用,可以接收任意子類的對象

【JavaSE】面向?qū)ο缶幊趟枷胫鄳B(tài)(圖文詳解),JavaSE,java,開發(fā)語言,ide,學(xué)習(xí)方法

3. 方法返回

作返回值:返回任意子類對象

【JavaSE】面向?qū)ο缶幊趟枷胫鄳B(tài)(圖文詳解),JavaSE,java,開發(fā)語言,ide,學(xué)習(xí)方法

向上轉(zhuǎn)型的優(yōu)點:讓代碼實現(xiàn)更簡單靈活。

向上轉(zhuǎn)型的缺陷:不能調(diào)用到子類特有的方法。

4.2 向下轉(zhuǎn)型

將一個子類對象經(jīng)過向上轉(zhuǎn)型之后當(dāng)成父類方法使用,再無法調(diào)用子類的方法,但有時候可能需要調(diào)用子類特有的方法,此時:將父類引用再還原為子類對象即可,即向下轉(zhuǎn)換。

【JavaSE】面向?qū)ο缶幊趟枷胫鄳B(tài)(圖文詳解),JavaSE,java,開發(fā)語言,ide,學(xué)習(xí)方法

?

class Animal {
    String name;
    int age;

    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void eat() {
        System.out.println(name + "吃飯");
    }
}

class Cat extends Animal {
    public Cat(String name, int age) {
        super(name, age);
    }

    @Override
    public void eat() {
        System.out.println(name + "吃魚~~~");
    }

    public void mew() {
        System.out.println(name + "喵喵叫");
    }
}


class Dog extends Animal {
    public Dog(String name, int age) {
        super(name, age);
    }

    @Override
    public void eat() {
        System.out.println(name + "吃骨頭~~~");
    }

    public void bark() {
        System.out.println(name + "汪汪叫");
    }
}

class Test {
    public static void main(String[] args) {
        Animal animal = new Dog("小狗", 1);
        Dog dog = (Dog) animal; //向下轉(zhuǎn)型
        dog.bark();
    }
}

上面的代碼時可以成功編譯的:

【JavaSE】面向?qū)ο缶幊趟枷胫鄳B(tài)(圖文詳解),JavaSE,java,開發(fā)語言,ide,學(xué)習(xí)方法

但是,當(dāng)main方法寫成下面這樣時:

【JavaSE】面向?qū)ο缶幊趟枷胫鄳B(tài)(圖文詳解),JavaSE,java,開發(fā)語言,ide,學(xué)習(xí)方法

此時編譯器并沒有錯誤提示,但當(dāng)程序運行的時候就出錯了:

【JavaSE】面向?qū)ο缶幊趟枷胫鄳B(tài)(圖文詳解),JavaSE,java,開發(fā)語言,ide,學(xué)習(xí)方法

在上面的代碼中,存在一個類型轉(zhuǎn)換錯誤。在Test類的main方法中,嘗試將一個Animal對象轉(zhuǎn)換為Cat對象,這是不正確的,因為animal實際上是一個Dog對象,無法強制轉(zhuǎn)換為Cat對象。

向下轉(zhuǎn)型用的比較少,而且不安全,萬一轉(zhuǎn)換失敗,運行時就會拋異常。Java中為了提高向下轉(zhuǎn)型的安全性,引入 了 instanceof ,如果該表達式為true,則可以安全轉(zhuǎn)換。

class Test {
    public static void main(String[] args) {
        Animal animal = new Dog("小狗", 1);
        if(animal instanceof Cat){
            Cat cat = (Cat)animal;
            cat.mew();
        }else {
            System.out.println("dog 無法轉(zhuǎn)化為 cat");
        }
    }
}

輸出結(jié)果:?

【JavaSE】面向?qū)ο缶幊趟枷胫鄳B(tài)(圖文詳解),JavaSE,java,開發(fā)語言,ide,學(xué)習(xí)方法

?

5. 多態(tài)的優(yōu)缺點

假設(shè)有如下代碼:

class Shape {
    //屬性....
    public void draw() {
        System.out.println("畫圖形!");
    }
}

class Rect extends Shape {
    @Override
    public void draw() {
        System.out.println("?");
    }
}

class Cycle extends Shape {
    @Override
    public void draw() {
        System.out.println("●");
    }
}

class Flower extends Shape {
    @Override
    public void draw() {
        System.out.println("?");
    }
}

【使用多態(tài)的好處】

1. 能夠降低代碼的 "圈復(fù)雜度", 避免使用大量的 if - else

什么叫 "圈復(fù)雜度" ? 圈復(fù)雜度是一種描述一段代碼復(fù)雜程度的方式. 一段代碼如果平鋪直敘, 那么就比較簡單容易理解. 而如果有很多的條件分支或者循環(huán)語句, 就認(rèn)為理解起來更復(fù)雜. 因此我們可以簡單粗暴的計算一段代碼中條件語句和循環(huán)語句出現(xiàn)的個數(shù), 這個個數(shù)就稱為 "圈復(fù)雜度". 如果一個方法的圈復(fù)雜度太高, 就需要考慮重構(gòu). 不同公司對于代碼的圈復(fù)雜度的規(guī)范不一樣. 一般不會超過10。

例如我們現(xiàn)在需要打印的不是一個形狀了, 而是多個形狀. 如果不基于多態(tài), 實現(xiàn)代碼如下:

public static void drawShapes() {
        Rect rect = new Rect();
        Cycle cycle = new Cycle();
        Flower flower = new Flower();
        String[] shapes = {"cycle", "rect", "cycle", "rect", "flower"};
        for (String shape : shapes) {
            if (shape.equals("cycle")) {
                cycle.draw();
            } else if (shape.equals("rect")) {
                rect.draw();
            } else if (shape.equals("flower")) {
                flower.draw();
            }
        }
    }

如果使用使用多態(tài), 則不必寫這么多的 if - else 分支語句, 代碼更簡單.

public static void drawShapes() {
        // 我們創(chuàng)建了一個 Shape 對象的數(shù)組.
        Shape[] shapes = {new Cycle(), new Rect(), new Cycle(),
                new Rect(), new Flower()};
        for (Shape shape : shapes) {
            shape.draw();
        }
    }

2. 可擴展能力更強

如果要新增一種新的形狀, 使用多態(tài)的方式代碼改動成本也比較低.

class Triangle extends Shape {
    @Override
    public void draw() {
        System.out.println("△");
    }
}

對于類的調(diào)用者來說(drawShapes方法), 只要創(chuàng)建一個新類的實例就可以了, 改動成本很低. 而對于不用多態(tài)的情況, 就要把 drawShapes 中的 if - else 進行一定的修改, 改動成本更高.

多態(tài)缺陷:代碼的運行效率降低。

1. 屬性沒有多態(tài)性

????????當(dāng)父類和子類都有同名屬性的時候,通過父類引用,只能引用父類自己的成員屬性

2. 構(gòu)造方法沒有多態(tài)性

6. 避免在構(gòu)造方法中調(diào)用重寫的方法

一段有坑的代碼. 我們創(chuàng)建兩個類, B 是父類, D 是子類. D 中重寫 func 方法. 并且在 B 的構(gòu)造方法中調(diào)用 func

class B {
    public B() {
        // do nothing
        func();
    }

    public void func() {
        System.out.println("B.func()");
    }
}

class D extends B {
    private int num = 1;

    @Override
    public void func() {
        System.out.println("D.func() " + num);
    }
}

public class Test {
    public static void main(String[] args) {
        D d = new D();
    }
}

代碼分析:?

【JavaSE】面向?qū)ο缶幊趟枷胫鄳B(tài)(圖文詳解),JavaSE,java,開發(fā)語言,ide,學(xué)習(xí)方法

  1. 構(gòu)造 D 對象的同時, 會調(diào)用 B 的構(gòu)造方法.
  2. B 的構(gòu)造方法中調(diào)用了 func 方法, 此時會觸發(fā)動態(tài)綁定, 會調(diào)用到 D 中的 func
  3. 此時 D 對象自身還沒有構(gòu)造, 此時 num 處在未初始化的狀態(tài), 值為 0. 如果具備多態(tài)性,num的值應(yīng)該是1.
  4. 所以在構(gòu)造函數(shù)內(nèi),盡量避免使用實例方法,除了final和private方法。

?輸出結(jié)果:【JavaSE】面向?qū)ο缶幊趟枷胫鄳B(tài)(圖文詳解),JavaSE,java,開發(fā)語言,ide,學(xué)習(xí)方法

結(jié)論: "用盡量簡單的方式使對象進入可工作狀態(tài)", 盡量不要在構(gòu)造器中調(diào)用方法(如果這個方法被子類重寫, 就會觸發(fā)動態(tài)綁定, 但是此時子類對象還沒構(gòu)造完成), 可能會出現(xiàn)一些隱藏的但是又極難發(fā)現(xiàn)的問題.

【JavaSE】面向?qū)ο缶幊趟枷胫鄳B(tài)(圖文詳解),JavaSE,java,開發(fā)語言,ide,學(xué)習(xí)方法

?

到了這里,關(guān)于【JavaSE】面向?qū)ο缶幊趟枷胫鄳B(tài)(圖文詳解)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包