Java基礎知識學習:Java三大特效之多態!

2020-12-03 黑馬程式設計師

1.1 多態的形式

多態是繼封裝、繼承之後,面向對象的第三大特性。

多態是出現在繼承或者實現關係中的。

多態體現的格式:

父類類型 變量名 = new 子類/實現類構造器;變量名.方法名();

多態的前提:有繼承關係,子類對象是可以賦值給父類類型的變量。例如Animal是一個動物類型,而Cat是一個貓類型。Cat繼承了Animal,Cat對象也是Animal類型,自然可以賦值給父類類型的變量。

1.2 多態的案例演示

當使用多態方式調用方法時,首先檢查父類中是否有該方法,如果沒有,則編譯錯誤;如果有,執行的是子類重寫後方法。如果子類沒有重寫該方法,就會調用父類的該方法。

總結起來就是:編譯看左邊,運行看右邊。

代碼如下:

定義父類:

public class Animal { public void eat(){ System.out.println("動物吃東西!")}

定義子類:

class Cat extends Animal { public void eat() { System.out.println("吃魚"); } } class Dog extends Animal { public void eat() { System.out.println("吃骨頭"); } }

定義測試類:

public class Test {public static void main(String[] args) { // 多態形式,創建對象 Animal a1 = new Cat(); // 調用的是 Cat 的 eat a1.eat(); // 多態形式,創建對象 Animal a2 = new Dog(); // 調用的是 Dog 的 eat a2.eat(); } }

1.3 多態的定義和前提

多態: 是指同一行為,具有多個不同表現形式。

從上面案例可以看出,Cat和Dog都是動物,都是吃這一行為,但是出現的效果(表現形式)是不一樣的。

前提【重點】

繼承或者實現【二選一】方法的重寫【意義體現:不重寫,無意義】父類引用指向子類對象【格式體現】父類類型:指子類對象繼承的父類類型,或者實現的父接口類型。1.4 多態的好處

實際開發的過程中,父類類型作為方法形式參數,傳遞子類對象給方法,進行方法的調用,更能體現出多態的擴展性與便利。代碼如下:

定義父類:

public abstract class Animal { public abstract void eat(); }

定義子類:

class Cat extends Animal { public void eat() { System.out.println("吃魚"); } } class Dog extends Animal { public void eat() { System.out.println("吃骨頭"); } }

定義測試類:

public class Test {public static void main(String[] args) { // 多態形式,創建對象 Cat c = new Cat(); Dog d = new Dog(); // 調用showCatEat showCatEat(c); // 調用showDogEat showDogEat(d); /* 以上兩個方法, 均可以被showAnimalEat(Animal a)方法所替代 而執行效果一致 */ showAnimalEat(c); showAnimalEat(d); } public static void showCatEat (Cat c){ c.eat(); } public static void showDogEat (Dog d){ d.eat(); } public static void showAnimalEat (Animal a){ a.eat(); }}

由於多態特性的支持,showAnimalEat方法的Animal類型,是Cat和Dog的父類類型,父類類型接收子類對象,當然可以把Cat對象和Dog對象,傳遞給方法。

當eat方法執行時,多態規定,執行的是子類重寫的方法,那麼效果自然與showCatEat、showDogEat方法一致,所以showAnimalEat完全可以替代以上兩方法。

不僅僅是替代,在擴展性方面,無論之後再多的子類出現,我們都不需要編寫showXxxEat方法了,直接使用showAnimalEat都可以完成。從而實現了實現類的自動切換。

所以,多態的好處,體現在,可以使程序編寫的更簡單,並有良好的擴展。

1.5 多態的弊端

我們已經知道多態編譯階段是看左邊父類類型的,如果子類有些獨有的功能,此時多態的寫法就無法訪問子類獨有功能了。

class Animal{public void eat(){ System.out.println("動物吃東西!")}class Cat extends Animal { public void eat() { System.out.println("吃魚"); } public void catchMouse() { System.out.println("抓老鼠"); } } class Dog extends Animal { public void eat() { System.out.println("吃骨頭"); } }class Test{ public static void main(String[] args){ Animal a = new Cat(); a.eat(); a.catchMouse();//編譯報錯,編譯看左邊,Animal沒有這個方法 }}

1.6 引用類型轉換

1.6.1 為什麼要轉型

多態的寫法就無法訪問子類獨有功能了。

當使用多態方式調用方法時,首先檢查父類中是否有該方法,如果沒有,則編譯錯誤。也就是說,不能調用子類擁有,而父類沒有的方法。編譯都錯誤,更別說運行了。這也是多態給我們帶來的一點"小麻煩"。所以,想要調用子類特有的方法,必須做向下轉型。

回顧基本數據類型轉換

自動轉換: 範圍小的賦值給範圍大的.自動完成:double d = 5;強制轉換: 範圍大的賦值給範圍小的,強制轉換:int i = (int)3.14多態的轉型分為向上轉型(自動轉換)與向下轉型(強制轉換)兩種。

1.6.2 向上轉型(自動轉換)

向上轉型:多態本身是子類類型向父類類型向上轉換(自動轉換)的過程,這個過程是默認的。 當父類引用指向一個子類對象時,便是向上轉型。 使用格式:父類類型 變量名 =new 子類類型();如:Animal a =newCat();

原因是:父類類型相對與子類來說是大範圍的類型,Animal是動物類,是父類類型。Cat是貓類,是子類類型。Animal類型的範圍當然很大,包含一切動物。所以子類範圍小可以直接自動轉型給父類類型的變量。

1.6.3 向下轉型(強制轉換)

向下轉型:父類類型向子類類型向下轉換的過程,這個過程是強制的。 一個已經向上轉型的子類對象,將父類引用轉為子類引用,可以使用強制類型轉換的格式,便是向下轉型。使用格式:

子類類型 變量名 =(子類類型) 父類變量名;如:Aniaml a =newCat(); Cat c =(Cat) a;

1.6.4 案例演示

當使用多態方式調用方法時,首先檢查父類中是否有該方法,如果沒有,則編譯錯誤。也就是說,不能調用子類擁有,而父類沒有的方法。編譯都錯誤,更別說運行了。這也是多態給我們帶來的一點"小麻煩"。所以,想要調用子類特有的方法,必須做向下轉型。

轉型演示,代碼如下:

定義類:

abstract class Animal { abstract void eat(); } class Cat extends Animal { public void eat() { System.out.println("吃魚"); } public void catchMouse() { System.out.println("抓老鼠"); } } class Dog extends Animal { public void eat() { System.out.println("吃骨頭"); } public void watchHouse() { System.out.println("看家"); } }

定義測試類:

public class Test {public static void main(String[] args) { // 向上轉型 Animal a = new Cat(); a.eat(); // 調用的是 Cat 的 eat // 向下轉型 Cat c = (Cat)a; c.catchMouse(); // 調用的是 Cat 的 catchMouse } }

1.6.5 轉型的異常

轉型的過程中,一不小心就會遇到這樣的問題,請看如下代碼:

public class Test {public static void main(String[] args) { // 向上轉型 Animal a = new Cat(); a.eat(); // 調用的是 Cat 的 eat // 向下轉型 Dog d = (Dog)a; d.watchHouse(); // 調用的是 Dog 的 watchHouse 【運行報錯】 } }

這段代碼可以通過編譯,但是運行時,卻報出了 ClassCastException ,類型轉換異常!這是因為,明明創建了Cat類型對象,運行時,當然不能轉換成Dog對象的。

1.6.6 instanceof關鍵字

為了避免ClassCastException的發生,Java提供了 instanceof 關鍵字,給引用變量做類型的校驗,格式如下:

變量名 instanceof 數據類型 如果變量屬於該數據類型或者其子類類型,返回true。如果變量不屬於該數據類型或者其子類類型,返回false。

所以,轉換前,我們最好先做一個判斷,代碼如下:

public class Test {

public static void main(String[] args) {

// 向上轉型

Animal a = new Cat();

a.eat(); // 調用的是 Cat 的 eat

// 向下轉型

if (a instanceof Cat){

Cat c = (Cat)a;

c.catchMouse(); // 調用的是 Cat 的 catchMouse

} else if (a instanceof Dog){

Dog d = (Dog)a;

d.watchHouse(); // 調用的是 Dog 的 watchHouse

}

}

}

相關焦點

  • 深入分析java中的多態(從jvm角度分析)
    對於java中多態概念的理解一直是面試常問的問題,所以今天花了一些時間好好地整理了一下,力求從java虛擬機的角度來分析和理解多態。一、認識多態1、方法調用在Java中,方法調用有兩類,動態方法調用與靜態方法調用。
  • 用經典案例來幫助初學者解析Java的「多態」
    說到Java的「多態」特性,很多人都十分熟悉、了解;也有很多人仍然在理解或闡述時對此含糊不清。我這裡還是用我13年前給我們公司新員工做內部培訓時用到的看起來似乎有點老掉牙的、但是仍然十分經典的案例來重新給有需要的java愛好者呈現一下「多態」的奧秘所在!
  • JAVA面向對象的多態是個什麼東西?
    面向對象的三大特徵:封裝、繼承、多態。在前面已經說了過了封裝和繼承。今天就來聊聊剩下的多態。多態,從字面內容來看,就是多種形態,多種狀態。在java的面向對象中可以從以下兩個方面來講。01不同子類之間的多態在前面我們說繼承的時候說到,子類可以繼承到父類的方法,繼承後可以對方法進行重寫。
  • 面試頻率最高的簡單問題——Java類的三大基本特徵
    學習過Java的程式設計師都知道,java類有三大特徵——封裝、繼承和多態。下面的文章給大家詳細的介紹一下java的這三大特性。封裝封裝是將描述某類事物的數據與處理這些數據的函數封裝在一起,形成一個有機整體,稱為類。類所具有的的封裝性可使程序模塊具有良好的獨立性與可維護性。
  • 必學——Java抽象類、接口、多態
    –接口不可以被實例化–實現類必須實現接口的所有方法–實現類可以實現多個接口–接口中的變量都是靜態常量(4)、編碼實現3、多態:同一個引用類型,使用不同的實例而執行不同操作(1)使用多態實現思路–編寫父類–編寫子類,子類重寫父類方法 –運行時,使用父類的類型,子類的對象(2)實現多態的兩種形式
  • Java-類型轉換,使用強制向下轉型解決多態的弊端
    瀏覽器版本過低,暫不支持視頻播放1.1.java的類型轉換1.1.1.java的類型轉換自動向上轉型: 可以直接將子類型引用賦值給父類型變量,可以自動進行,叫做自動向上轉型;例如:class Fu{}class Zi extends Fu{}
  • Java多態,對象轉型,和簡單工廠模式 希望對您有幫助!
    各位讀者老爺們大家好鴨~圖圖又來了,今天我們要說一下「多態」。怎麼理解這兩個字呢?可以理解為同一個引用對象的不同表現形態,即將父類的引用指向子類的對象。這是比較官方的書面解釋,大家可以通過自己的理解轉化成自己的話。知道,了解一下就行。大家還需要知道的是:多態是java面向對象的三大特徵之一。
  • 用最傻瓜式的方法理解Java中的封裝、繼承和多態
    說到java中面向對象的封裝、繼承和多態,很多人會說這麼簡單這麼入門的東西一直講幹嘛,雖然是基礎,但是我們要明白,所有東西都是要在基礎上發展的,沒有基礎就去學其他的,那麼你肯定是很容易失敗的,那麼應該怎樣能夠用傻瓜式方法去理解Java面向對象的封裝、繼承和多態呢?
  • Java基礎學習:java中的基本數據類型
    +=運算符是java語言規定的,編譯器會對它進行識別處理,因此可以正確編譯。 三、Float和Dubble 1、基礎概念
  • Java基礎之多態,動態綁定多態的代碼案例,簡單卻很重要
    一、多態多態基於繼承(),現實事物中經常可以看到人,而學生、工人、白領、太空人等都是人,即由人演變而來的多種狀態。多態是Java三大特性(封裝、繼承、多態)之一,它的出現豐富了完善了Java面向對象體系。
  • Java基礎,類的繼承,粗略的理解希望對大家有所幫助!
    Java基礎:繼承讀者老爺們大家好,今天圖圖帶大家了解一下java基礎裡的繼承。首先確定一下我們今天的學習的三個目標。第一個是類的繼承;第二個是訪問控制權限;第三個方法重寫(覆蓋)override。好滴,話不多說,讓我們快樂的投身知識的海洋裡吧!
  • 程式設計師:深入理解JVM,從JVM層面來講Java多態
    對多態理解不夠深入的,多半都會答錯;如果能記住口訣:「變量多態看左邊,方法多態看右邊,靜態多態看左邊」的話,肯定就知道答案,但是JVM是如何確定具體調用哪個方法的,有小夥伴思考過嗎?與之對應的是,在JVM裡面提供了5條方法調用字節碼指令,分別如下:invokestatic:調用靜態方法invokespecial:調用實例構造器<init>方法、私有方法和父類方法。
  • Java 中的繼承和多態(深入版)
    面向對象的三大特性:封裝、繼承、多態。在這三個特性中,如果沒有封裝和繼承,也不會有多態。那麼多態實現的途徑和必要條件是什麼呢?以及多態中的重寫和重載在JVM中的表現是怎麼樣?在Java中是如何展現繼承的特性呢?對於子類繼承於父類時,又有什麼限制呢?
  • 學習java的優勢是什麼?學習難度怎麼樣
    學習java成為了現在比較熱門的話題。Java是一種可以撰寫跨平臺應用軟體的面向對象的程序設計語言。  他容易學而且很好用,如果你學習過C++語言,你會覺得C++和Java很像,因為Java中許多基本語句的語法和C++一樣,像常用的循環語句,控制語句等和C++幾乎一樣,其實Java和C++是兩種完全不同的語言,Java只需理解一些基本的概念,就可以用它編寫出適合於各種情況的應用程式。同時截止到2018年8月,java領先其它語言幾乎4.5%。為世界第一程式語言。
  • Java面向對象之final、abstract抽象、和變量生命周期
    Java面向對象之final、abstract抽象、final修飾符final運行命令如下:java 包名.類名;package命名:1.包名的定義:自定義的包名不能以java開頭,會和java語言基礎類庫衝突。
  • Java NIO 基礎知識
    也許你現在還不知道 NIO 有什麼用,但是一定不要放棄學習它。緩衝區操作緩衝區是 NIO 操作的核心,本質上 NIO 操作就是緩衝區操作。寫操作是將緩衝區的數據排乾,如將數據從緩衝區持久化到磁碟中。讀操作是將數據填充到緩衝區中,以便應用程式後續使用數據。當然,我們這裡說的緩衝區是指用戶空間的緩衝區。.
  • Java程式設計師必備基礎:Java代碼是怎麼運行的?
    java源文件編譯為class字節碼 類加載器把字節碼加載到虛擬機的方法區。但是java是一門面向對象的高級語言,它不僅語法非常複雜,抽象程度也非常高,並不能直接運行在計算機硬體機器上。 Java虛擬機(Java Virtual Machine 簡稱JVM)是運行所有Java程序的抽象計算機,是Java語言的運行環境。
  • Java面向對象之:封裝、繼承、多態
    Java面向對象之:封裝、繼承、多態高內聚和低耦合訪問權限修飾符應封裝的隱藏細節的理念,java提供了訪問權限修飾符來控制調用者的訪問權限,詳情如下:private:屬於類訪問權限,表示私有的,只能在當前類中訪問,使用private修飾的類、方法、欄位,在』離開當前類的作用域之後
  • 開發崗位這麼多,為什麼選Java?你學Java了嗎-開課吧
    其他程式語言與Java相比,Java語法相對簡單,並且是很多計算機語言的基礎。提到C++語言,很多人發現在使用過程中最容易出現的錯誤就是內存管理,而java有自動垃圾回收器,不用擔心內存。,招聘平臺上招程式設計師java佔比很高。
  • 學java可以做什麼?大數據前景和就業方向又是什麼樣的呢?
    學java可以做什麼?(1) Java可以用來做網站:很多大型網站都是用JSP寫的,JSP全名java server pages,這是一種動態網頁技術,比如我們熟悉的B站,很多政府網站都是用這個寫的所以想學習java的同學還可以負責網站方面的製作,這方面的崗位也比較多。