日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

【JavaSE系列】 第九话 —— 多态那些事儿

發(fā)布時(shí)間:2024/3/13 java 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【JavaSE系列】 第九话 —— 多态那些事儿 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

?導(dǎo)航小助手?

? 🍚前言

? 🍞思維導(dǎo)圖

? 🧇一、多態(tài)的概念

? 🧀二、向上轉(zhuǎn)型和向下轉(zhuǎn)型

? ? ? ? ? ? ? 🥡🥡2.1 向上轉(zhuǎn)型

? ? ? ? ? ? ? 🥨🥨2.2?什么是向上轉(zhuǎn)型

? ? ? ? ? ? ? 🥐🥐2.3?三種常見的向上轉(zhuǎn)型

? ? ? ? ? ? ? ? ? ? ? ? 🍔🍔🍔2.3.1?直接賦值

? ? ? ? ? ? ? ? ? ? ? ? 🍜🍜🍜2.3.2?作為方法的參數(shù)

? ? ? ? ? ? ? ? ? ? ? ? 🎂🎂🎂2.3.3?作為方法的返回值

? ? ? ? ? ? ? 🍤🍤2.4?向下轉(zhuǎn)型(這個(gè)了解即可)

? 🍰三、方法重寫

? ? ? ? ? ? ? 🍣🍣3.1 方法重寫的概念

? ? ? ? ? ? ? 🦪🦪3.2 方法重寫的規(guī)定

? ? ? ? ? ? ? 🥩🥩3.3 在IDEA中使用重寫的快捷方式???????

? ? ? ? ? ? ? 🍱🍱3.4 方法重寫中所要注意的細(xì)節(jié)

? 🍛四、多態(tài)

? ? ? ? ? ? ? 🍖🍖4.1 什么是多態(tài)

? ? ? ? ? ? ? 🥮🥮4.2 多態(tài)產(chǎn)生的前提

? 🍝五、理解多態(tài)

? 🥣六、多態(tài)的優(yōu)缺點(diǎn)

? ? ? ? ? ? ? 🥗🥗6.1 使用多態(tài)的好處???????

? ? ? ? ? ? ? 🍗🍗6.2 多態(tài)的缺點(diǎn)

? 🍲七、避免在構(gòu)造方法中調(diào)用重寫的方法

? 🍎寫在最后


前言

? ? ? ?本篇博客 博主來介紹 Java的三大特性的最后一個(gè) 特性 —— 多態(tài);

? ? ? ?當(dāng)然,也包括多態(tài)所涉及的多方面內(nèi)容;

? ? ? ?現(xiàn)在,拉長(zhǎng)耳朵,提高警覺,端起你們的小板凳;

? ? ? ?且聽我細(xì)細(xì)道來......


思維導(dǎo)圖

?


一、多態(tài)的概念

? ? ? ?多態(tài),

? ? ? ?從語(yǔ)文的層次上來說:一種事務(wù),多種形態(tài);這句話不算對(duì),但也不算錯(cuò);

? ? ? ?但是,我們需要從程序的角度上來介紹:去完成某個(gè)行為,當(dāng)不同的對(duì)象去完成時(shí),會(huì)產(chǎn)生不同的狀態(tài),這就是多態(tài)。

? ? ? ?比如說,如下圖所示:同樣是一個(gè)打印機(jī),去打印相同的照片;但是,交給彩色打印機(jī)打印出來的就是彩色的照片;交給黑白打印機(jī)打印出來的就是黑白照片;它們完成的動(dòng)作都是“打印”;這就是一種多態(tài);

? ? ? ?再比如說,如下圖所示,去“吃飯”,對(duì)于小貓來說,吃的是“貓糧”;但對(duì)于小狗來說,吃的確是“狗糧”;他們完成的都是“吃飯”這個(gè)行為,但是卻“吃出不同的結(jié)果來”; 這也是一種多態(tài);

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

聽到這里,是不是還是對(duì)于 多態(tài) 有點(diǎn)頭暈;

那么,要想真正了解多態(tài),我們還是需要從三個(gè)方面來介紹:

  • 什么是向上轉(zhuǎn)型;
  • 什么叫做方法重寫;
  • 了解了前兩個(gè),我們才會(huì)真正了解什么是多態(tài)。
  • 下面,我會(huì)一一的介紹......


    二、向上轉(zhuǎn)型和向下轉(zhuǎn)型

    2.1 向上轉(zhuǎn)型

    ? ? ? ?當(dāng)然的是,有了 向上轉(zhuǎn)型,那么肯定也會(huì)有向下轉(zhuǎn)型,

    向下轉(zhuǎn)型 會(huì)在后面講到......

    2.2?什么是向上轉(zhuǎn)型

    ? ? ? ?首先介紹一段平平常常的繼承代碼:

    package Demo1; class Animal {public String name;public int age;public void eat() {System.out.println(this.name+"吃飯!");} }class Cat extends Animal {public String hair;public void mew() {System.out.println(this.name+"正在叫!");} }public class TestDemo1 {public static void main(String[] args) {Cat cat = new Cat();cat.mew();} }

    ? ? ? ?那么,如果現(xiàn)在拋開 繼承 不談,直接用Animal類 new一個(gè)animal對(duì)象,可以發(fā)現(xiàn),animal對(duì)象訪問不了Animal類 里面沒有的成員變量 或成員方法:

    ? ? ? ?接下來,可以來講一講 向上轉(zhuǎn)型 的知識(shí)了:

    ? ? ? ?這里的 上 指的是 父類,那么 下 指的就是 子類;

    ? ? ? ? 那么,把子類給父類是什么意思呢?

    //即:定義類一個(gè) cat//可以用animal來接收//也就是說,父類的引用 可以用來引用 子類的對(duì)象Cat cat = new Cat();Animal animal = cat;//也就是說,上面的兩行代碼,可以合并成下面一行代碼Animal animal = new Cat();//此時(shí),父類的引用 引用了 子類的對(duì)象,我們把這個(gè)就叫做 向上轉(zhuǎn)型

    ? ? ? ?但是,此時(shí)又有一個(gè)新的問題;

    ? ? ? ?animal的類型是Animal,那么 此時(shí)它只能去訪問 類Animal 的成員變量和方法,去訪問 子類Cat的成員變量或方法的時(shí)候會(huì)報(bào)錯(cuò):

    ?

    【總結(jié)】

    ? ? ? ?向上轉(zhuǎn)型,把原來的 子類的類型 轉(zhuǎn)換成了 父類的類型,那么,就只能去訪問 父類特有的成員方法或者成員變量。

    2.3?三種常見的向上轉(zhuǎn)型

    2.3.1?直接賦值

    ? ? ? ?所謂直接賦值,就是 上面的直接把 子類對(duì)象 給 父類 進(jìn)行引用:

    /*Cat cat = new Cat();Animal animal = cat;*/Animal animal = new Cat();

    2.3.2?作為方法的參數(shù)

    2.3.3?作為方法的返回值

    2.4?向下轉(zhuǎn)型(這個(gè)了解即可)

    前面已經(jīng)介紹過 向上轉(zhuǎn)型,那么 現(xiàn)在來介紹一下 向下轉(zhuǎn)型:

    不過,現(xiàn)在來執(zhí)行一下這樣的操作:

    此時(shí),運(yùn)行結(jié)果:

    但是,向下轉(zhuǎn)型不安全(不介意使用向下轉(zhuǎn)型):

    ?我們還需要做以下修改 以保證其安全性:

    【注意】


    三、方法重寫

    ? ? ? ?由上面可知,父類引用引用了子類的對(duì)象;

    ? ? ? ?但是,在現(xiàn)實(shí)生活中,貓是吃貓糧的;

    ? ? ? ?那么,如果想改的話,肯定不可以在父類上面進(jìn)行修改的;

    ? ? ? ?畢竟,可能還有 其他的子類 來繼承父類;

    ? ? ? ?那么,如果想修改的話,就需要在子類里面重新取實(shí)現(xiàn)一遍這個(gè)方法的:

    ? ? ? ?然后,我們來對(duì)比一下 實(shí)現(xiàn)前后的結(jié)果:

    沒有在子類里面寫eat方法:

    在子類里面寫了eat方法:

    ?這是怎么回事呢?

    ——這就是馬上所要介紹的方法重寫

    3.1 方法重寫的概念

    ? ? ? ?重寫,也稱為覆蓋;

    ? ? ? ?重寫,是子類對(duì)父類 非靜態(tài)、非private修飾、非final修飾、非構(gòu)造方法 等的實(shí)現(xiàn)過程進(jìn)行重新編寫;

    ? ? ? ?重寫的好處是:子類可以根據(jù)需要,定義特定的屬于自己的行為;如 上面的貓可以吃貓糧,狗可以吃狗糧。

    3.2 方法重寫的規(guī)定

    方法重寫滿足以下三個(gè)條件:

  • 方法的名稱相同;
  • 方法的返回值相同;
  • 方法的參數(shù)列表相同。
  • ? ? ? ?當(dāng)在子類 方法重寫以后,那么就會(huì)調(diào)用的是 子類重寫的內(nèi)容。

    ? ? ? ?我們把這個(gè)現(xiàn)象叫做動(dòng)態(tài)綁定(這是多態(tài)的基礎(chǔ))

    ? ? ? ?傳送門:動(dòng)態(tài)綁定

    ? ? ? ?在上面所示例中,

    ? ? ? ?在編譯的時(shí)候,調(diào)用的還是 父類Animal的eat方法;

    ? ? ? ?但是,在運(yùn)行的時(shí)候,變成了子類Cat自己的eat方法;

    ? ? ? ?因此,動(dòng)態(tài)綁定又稱為 運(yùn)行時(shí)綁定

    ? ? ? ?即:在程序運(yùn)行的時(shí)候才知道要調(diào)用誰。

    ? ? ? ?當(dāng)然,有了 動(dòng)態(tài)綁定,那肯定也有 靜態(tài)綁定:

    ? ? ? ?在編譯期間就已經(jīng)知道了 要調(diào)用的是誰,

    ? ? ? ?比如說 重載。

    3.3 在IDEA中使用重寫的快捷方式

    ? ? ? ?當(dāng)然,在使用IDEA編譯器的時(shí)候 ,

    ? ? ? ?重寫不僅僅可以直接在子類上手敲出來的(上面的就是),而且還可以使用快捷鍵的方式:

    ?

    【注意】上面的 @Override 就是重寫的意思。

    ?

    3.4 方法重寫中所要注意的細(xì)節(jié)

  • 靜態(tài)方法(static修飾)是構(gòu)成不了重寫的:
  • private修飾 的方法不能進(jìn)行重寫:
  • 如果要進(jìn)行重寫的話,那么 子類的 訪問限定修飾符的權(quán)限 一定 大于等于 父類的訪問限定修飾符
  • 被final修飾的方法不可以進(jìn)行重寫:
  • 子類和父類在同一個(gè)包中,那么子類可以重寫父類的所有方法(除了 聲明為private和final的方法);子類和父類不在同一個(gè)包,那么子類只能夠 重寫父類的 聲明為public和protected的非final的方法(即 默認(rèn)權(quán)限方法/包訪問權(quán)限 不可以被重寫);
  • 重寫的方法,可以使用 @Override 注解來顯示指定;有了這個(gè)注解 可以幫助我們進(jìn)行一些合法性校驗(yàn);如 不小心把方法名字寫錯(cuò)了(寫成ate),那么此時(shí)編譯器就會(huì)發(fā)現(xiàn)父類中沒有ate方法,就會(huì)編譯報(bào)錯(cuò),提示無法構(gòu)成重寫。
  • ?訪問限定符權(quán)限大小比較:

    private < default < peotected < public??

    ?


    四、多態(tài)

    4.1 什么是多態(tài)

    類的實(shí)現(xiàn)者所寫的代碼:

    class Animal {public String name;public int age;public void eat() {System.out.println(this.name+"吃飯!父類Animal");} }class Cat extends Animal {public String hair;public void eat(){System.out.println(this.name+"吃貓糧!");}public void mew() {System.out.println(this.name+"正在叫!");} } class Dog extends Animal {public void eat(){System.out.println(this.name+"吃狗糧!");} }

    類的調(diào)用者所寫的代碼:

    public static void function(Animal animal) {animal.eat();}public static void main(String[] args) {Cat cat = new Cat();Dog dog = new Dog();function(cat);function(dog);}

    ?

    所以運(yùn)行之后得到的結(jié)果不一樣:

    ? ? ? ?從上面可以得到,同一個(gè)方法,當(dāng)引用的對(duì)象不一樣的時(shí)候,這個(gè)方法所表現(xiàn)出來的行為是不一樣的;

    ? ? ? ?我們把這種思想就叫做 多態(tài)。?

    4.2 多態(tài)產(chǎn)生的前提

  • 發(fā)生向上轉(zhuǎn)型:父類引用 引用子類的對(duì)象;
  • 發(fā)生重寫:父類和子類當(dāng)中 有同名的覆蓋方法;
  • 通過父類引用,調(diào)用這個(gè)重寫的方法,此時(shí)會(huì)發(fā)生 動(dòng)態(tài)綁定。
  • 思想:通過一個(gè)引用調(diào)用一個(gè)方法,由于引用的對(duì)象不同,所執(zhí)行的行為也是不一樣的;我們把這種思想就叫做多態(tài)的思想。


    五、理解多態(tài)

    現(xiàn)在再次回顧一下多態(tài):

    場(chǎng)景:現(xiàn)在想畫一個(gè)圖形(圖形是未知的):

    首先,創(chuàng)建父類:

    class Shape {//省略了長(zhǎng)、寬、高等之類的屬性public void draw(){System.out.println("畫圖形!!!!!!");}}

    創(chuàng)建父類Shape只是畫父類,但是并沒有說明畫什么;

    現(xiàn)在想畫各種各樣的圖形,那么就可以去重寫 Shape類里面的draw方法來滿足自己的需求:

    class Cycle extends Shape {@Overridepublic void draw() {System.out.println("○");} }class Rect extends Shape {@Overridepublic void draw() {System.out.println(" ? ");} }class Triangle extends Shape {@Overridepublic void draw() {System.out.println("△");} }

    前面兩段代碼都是類的實(shí)現(xiàn)者寫的;

    當(dāng)有一天作為用戶、作為類的調(diào)用者 想要畫出這些圖形,那么就可以這樣來做:

    public static void drawMap(Shape shape) {shape.draw();}public static void main(String[] args) {Cycle cycle = new Cycle();Rect rect = new Rect();Triangle triangle = new Triangle();drawMap(cycle);drawMap(rect);drawMap(triangle);}

    那么,根據(jù)引用的對(duì)象不一樣,draw方法所表現(xiàn)的行為就不一樣;

    這個(gè)就叫做 多態(tài)。

    代碼示例結(jié)果:

    由此可見,多態(tài)只是一種思想,需要滿足三個(gè)條件;

    那么,多態(tài)到底有什么好處呢?

    ——其拓展能力非常強(qiáng):

    如果突然說,現(xiàn)在想要畫一朵花:

    那么只需要在這樣做即可:

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

    測(cè)試類添上這個(gè)來測(cè)試:

    drawMap(new Flower());

    代碼示例結(jié)果:


    六、多態(tài)的優(yōu)缺點(diǎn)

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

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

    ? ? ? ? ? ??傳送門——圈復(fù)雜度??????

    ? ? ? ? ? ?說白了,可以簡(jiǎn)單粗暴的計(jì)算 一段代碼中條件語(yǔ)句和循環(huán)語(yǔ)句 出現(xiàn)的個(gè)數(shù),這個(gè)個(gè)數(shù)就稱為 "圈復(fù)雜度";

    ? ? ? ? ? ? 如果一個(gè)方法的 圈復(fù)雜度 太高,就需要考慮重構(gòu)。

    (2)可擴(kuò)展能力強(qiáng);?

    ? ? ? ? ? ? 就是上面所說的 添加了一朵花的 示例。

    6.2 多態(tài)的缺點(diǎn)

    ? ? ? ? ? ? ? ? ? ? ?代碼的運(yùn)行效率低。


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

    class B {public B(){func();}public void func() {System.out.println("B.func() ");} }class D extends B {D(){super();}@Overridepublic void func() {System.out.println("D.func() ");} }public class Test {public static void main(String[] args) {D d = new D();} }

    代碼示例結(jié)果:

    ?【說明】

  • 構(gòu)造D對(duì)象的同時(shí),會(huì)調(diào)用B的構(gòu)造方法;
  • B的構(gòu)造方法中調(diào)用了 func方法,此時(shí)會(huì)觸發(fā) 動(dòng)態(tài)綁定,會(huì)調(diào)用到D中的 func;
  • 【注意】最好盡量不要寫類似的代碼——避免在構(gòu)造方法中調(diào)用重寫的方法。


    寫在最后

    ? ? ? ?到現(xiàn)在,Java三大特性的最后一個(gè)特性——多態(tài)思想 就已經(jīng)告一段落了;

    ? ? ? ?由于博主水平有限,可能會(huì)出現(xiàn)一些表達(dá)不清楚,或者出現(xiàn)一些其他的情況,

    ? ? ? ?歡迎各位鐵汁們指出來,和博主一起改正,

    ? ? ? ?一起努力,共同進(jìn)步;

    ? ? ? ?好了,如果這篇博客對(duì)鐵汁們有幫助的話,可以送一個(gè)免費(fèi)的 贊 嘛;

    ? ? ? ?當(dāng)然,順手點(diǎn)個(gè)關(guān)注是再好不過的了......

    ?

    總結(jié)

    以上是生活随笔為你收集整理的【JavaSE系列】 第九话 —— 多态那些事儿的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。