最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java多態(tài)性定義與用法實例詳解

 更新時間:2017年09月26日 10:46:39   作者:dackwind  
這篇文章主要介紹了Java多態(tài)性定義與用法,較為詳細的分析了多態(tài)的概念、功能以及java定義與實現(xiàn)面向對象多態(tài)性的相關操作技巧,需要的朋友可以參考下

本文實例講述了Java多態(tài)性定義與用法。分享給大家供大家參考,具體如下:

多態(tài)性是通過:

1 接口和實現(xiàn)接口并覆蓋接口中同一方法的幾不同的類體現(xiàn)的

2 父類和繼承父類并覆蓋父類中同一方法的幾個不同子類實現(xiàn)的.

一、基本概念

多態(tài)性:發(fā)送消息給某個對象,讓該對象自行決定響應何種行為 。通過將子類對象引用賦值給超類對象引用變量來實現(xiàn)動態(tài)方法調用 。

java 的這種機制遵循一個原則:當超類對象引用變量引用子類對象時,被引用對象的類型而不是引用變量的類型決定了調用誰的成員方法,但是這個被調用的方法必須是在超類中定義過的,也就是說被子類覆蓋的方法 。

如果a是類A的一個引用,那么,a可以指向類A的一個實例,或者說指向類A的一個子類 。

如果a是接口A的一個引用,那么,a必須指向實現(xiàn)了接口A的一個類的實例 。

二、Java多態(tài)性實現(xiàn)機制

SUN目前的JVM實現(xiàn)機制,類實例的引用就是指向一個句柄(handle)的指針,這個句柄是一對指針:

一個指針指向一張表格,實際上這個表格也有兩個指針(一個指針指向一個包含了對象的方法表,另外一個指向類對象,表明該對象所屬的類型);

另一個指針指向一塊從java堆中為分配出來內存空間 。

三、總結

1、通過將子類對象引用賦值給超類對象引用變量來實現(xiàn)動態(tài)方法調用 。

DerivedC c2=new DerivedC();
BaseClass a1= c2; //BaseClass 基類,DerivedC是繼承自BaseClass的子類
a1.play(); //play()在BaseClass,DerivedC中均有定義,即子類覆寫了該方法

分析:

1、為什么子類的類型的對象實例可以覆給超類引用?

自動實現(xiàn)向上轉型 。通過該語句,編譯器自動將子類實例向上移動,成為通用類型BaseClass;

2、a.play()將執(zhí)行子類還是父類定義的方法?

子類的 。在運行時期,將根據(jù)a這個對象引用實際的類型來獲取對應的方法 。所以才有多態(tài)性 。一個基類的對象引用,被賦予不同的子類對象引用,執(zhí)行該方法時,將表現(xiàn)出不同的行為 。

在a1=c2的時候,仍然是存在兩個句柄,a1和c2,但是a1和c2擁有同一塊數(shù)據(jù)內存塊和不同的函數(shù)表 。

2、不能把父類對象引用賦給子類對象引用變量

BaseClass a2=new BaseClass();
DerivedC c1=a2;//出錯

在java里面,向上轉型是自動進行的,但是向下轉型卻不是,需要我們自己定義強制進行 。

c1=(DerivedC)a2; 進行強制轉化,也就是向下轉型.

3、記住一個很簡單又很復雜的規(guī)則,一個類型引用只能引用引用類型自身含有的方法和變量 。

你可能說這個規(guī)則不對的,因為父類引用指向子類對象的時候,最后執(zhí)行的是子類的方法的 。

其實這并不矛盾,那是因為采用了后期綁定,動態(tài)運行的時候又根據(jù)型別去調用了子類的方法 。而假若子類的這個方法在父類中并沒有定義,則會出錯 。

例如,DerivedC類在繼承BaseClass中定義的函數(shù)外,還增加了幾個函數(shù)(例如 myFun())

分析:

當你使用父類引用指向子類的時候,其實jvm已經(jīng)使用了編譯器產(chǎn)生的類型信息調整轉換了 。

這里你可以這樣理解,相當于把不是父類中含有的函數(shù)從虛擬函數(shù)表中設置為不可見的 。注意有可能虛擬函數(shù)表中有些函數(shù)地址由于在子類中已經(jīng)被改寫了,所以對象虛擬函數(shù)表中虛擬函數(shù)項目地址已經(jīng)被設置為子類中完成的方法體的地址了 。

4、Java與C++多態(tài)性的比較

jvm關于多態(tài)性支持解決方法是和c++中幾乎一樣的,只是c++中編譯器很多是把類型信息和虛擬函數(shù)信息都放在一個虛擬函數(shù)表中,但是利用某種技術來區(qū)別 。

Java把類型信息和函數(shù)信息分開放 。Java中在繼承以后,子類會重新設置自己的虛擬函數(shù)表,這個虛擬函數(shù)表中的項目有由兩部分組成 。從父類繼承的虛擬函數(shù)和子類自己的虛擬函數(shù) 。

虛擬函數(shù)調用是經(jīng)過虛擬函數(shù)表間接調用的,所以才得以實現(xiàn)多態(tài)的 。Java的所有函數(shù),除了被聲明為final的,都是用后期綁定 。

四. 1個行為,不同的對象,他們具體體現(xiàn)出來的方式不一樣,

比如: 方法重載 overloading 以及 方法重寫(覆蓋)override

class Human{
void run(){輸出 人在跑}
}
class Man extends Human{
void run(){輸出 男人在跑}
}

這個時候,同是跑,不同的對象,不一樣(這個是方法覆蓋的例子)

class Test{
void out(String str){輸出 str}
void out(int i){輸出 i}
}

這個例子是方法重載,方法名相同,參數(shù)表不同

ok,明白了這些還不夠,還用人在跑舉例

Human ahuman=new Man();

這樣我等于實例化了一個Man的對象,并聲明了一個Human的引用,讓它去指向Man這個對象

意思是說,把 Man這個對象當 Human看了.

比如去動物園,你看見了一個動物,不知道它是什么, “這是什么動物? ” “這是大熊貓! “

這2句話,就是最好的證明,因為不知道它是大熊貓,但知道它的父類是動物,所以,這個大熊貓對象,你把它當成其父類 動物看,這樣子合情合理.這種方式下要注意 new Man();的確實例化了Man對象,所以ahuman.run()這個方法 輸出的 是 “男人在跑 “如果在子類 Man下你 寫了一些它獨有的方法 比如 eat(),而Human沒有這個方法,在調用eat方法時,一定要注意 強制類型轉換 ((Man)ahuman).eat(),這樣才可以…

對接口來說,情況是類似的…

package domatic;
//定義超類superA
class superA {
int i = 100;
void fun(int j) {
j = i;
System.out.println("This is superA");
}
}
// 定義superA的子類subB
class subB extends superA {
int m = 1;
void fun(int aa) {
System.out.println("This is subB");
}
}
// 定義superA的子類subC
class subC extends superA {
int n = 1;
void fun(int cc) {
System.out.println("This is subC");
}
}
class Test {
public static void main(String[] args) {
superA a = new superA();
subB b = new subB();
subC c = new subC();
a = b;
a.fun(100);
a = c;
a.fun(200);
}
}

/*
* 上述代碼中subB和subC是超類superA的子類,我們在類Test中聲明了3個引用變量a, b,
* c,通過將子類對象引用賦值給超類對象引用變量來實現(xiàn)動態(tài)方法調用 。也許有人會問:
* “為什么(1)和(2)不輸出:This is superA” 。
* java的這種機制遵循一個原則:當超類對象引用變量引用子類對象時,
* 被引用對象的類型而不是引用變量的類型決定了調用誰的成員方法,
* 但是這個被調用的方法必須是在超類中定義過的,
* 也就是說被子類覆蓋的方法 。
* 所以,不要被上例中(1)和(2)所迷惑,雖然寫成a.fun(),但是由于(1)中的a被b賦值,
* 指向了子類subB的一個實例,因而(1)所調用的fun()實際上是子類subB的成員方法fun(),
* 它覆蓋了超類superA的成員方法fun();同樣(2)調用的是子類subC的成員方法fun() 。
* 另外,如果子類繼承的超類是一個抽象類,雖然抽象類不能通過new操作符實例化,
* 但是可以創(chuàng)建抽象類的對象引用指向子類對象,以實現(xiàn)運行時多態(tài)性 。具體的實現(xiàn)方法同上例 。
* 不過,抽象類的子類必須覆蓋實現(xiàn)超類中的所有的抽象方法,
* 否則子類必須被abstract修飾符修飾,當然也就不能被實例化了
*/

以上大多數(shù)是以子類覆蓋父類的方法實現(xiàn)多態(tài).下面是另一種實現(xiàn)多態(tài)的方法———–重寫父類方法

1.JAVA里沒有多繼承,一個類之能有一個父類 。而繼承的表現(xiàn)就是多態(tài) 。一個父類可以有多個子類,而在子類里可以重寫父類的方法(例如方法print()),這樣每個子類里重寫的代碼不一樣,自然表現(xiàn)形式就不一樣 。這樣用父類的變量去引用不同的子類,在調用這個相同的方法print()的時候得到的結果和表現(xiàn)形式就不一樣了,這就是多態(tài),相同的消息(也就是調用相同的方法)會有不同的結果 。舉例說明:

//父類
public class Father{
//父類有一個打孩子方法
public void hitChild(){
}
}
//子類1
public class Son1 extends Father{
//重寫父類打孩子方法
public void hitChild(){
System.out.println("為什么打我?我做錯什么了!");
}
}
//子類2
public class Son2 extends Father{
//重寫父類打孩子方法
public void hitChild(){
System.out.println("我知道錯了,別打了!");
}
}
//子類3
public class Son3 extends Father{
//重寫父類打孩子方法
public void hitChild(){
System.out.println("我跑,你打不著!");
}
}
//測試類
public class Test{
public static void main(String args[]){
Father father;
father = new Son1();
father.hitChild();
father = new Son2();
father.hitChild();
father = new Son3();
father.hitChild();
}
}

都調用了相同的方法,出現(xiàn)了不同的結果!這就是多態(tài)的表現(xiàn)!

更多java相關內容感興趣的讀者可查看本站專題:《Java面向對象程序設計入門與進階教程》、《Java數(shù)據(jù)結構與算法教程》、《Java操作DOM節(jié)點技巧總結》、《Java文件與目錄操作技巧匯總》和《Java緩存操作技巧匯總

希望本文所述對大家java程序設計有所幫助。

相關文章

  • 詳解使用批處理方式配置Java環(huán)境

    詳解使用批處理方式配置Java環(huán)境

    這篇文章主要介紹了詳解使用批處理方式配置Java環(huán)境,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-09-09
  • Java中DecimalFormat用法及符號含義

    Java中DecimalFormat用法及符號含義

    DecimalFormat是NumberFormat的一個具體子類,用于格式化十進制數(shù)字。這篇文章介紹了DecimalFormat的用法及符號含義,需要的朋友可以收藏下,方便下次瀏覽觀看
    2021-12-12
  • Mybatis如何分割字符串

    Mybatis如何分割字符串

    這篇文章主要介紹了Mybatis如何分割字符串問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • SpringCloud Gateway鑒權和跨域解決方案

    SpringCloud Gateway鑒權和跨域解決方案

    網(wǎng)關是介于客戶端和服務器端之間的中間層,所有的外部請求都會先經(jīng)過 網(wǎng)關這一層,也就是說,API 的實現(xiàn)方面更多的考慮業(yè)務邏輯,而安全、性能、監(jiān)控可以交由 網(wǎng)關來做,這樣既提高業(yè)務靈活性又不缺安全性,本文給大家介紹SpringCloud Gateway鑒權和跨域解決方案,一起看看吧
    2023-11-11
  • win10安裝JDK14.0.2的詳細安裝過程

    win10安裝JDK14.0.2的詳細安裝過程

    這篇文章主要介紹了win10安裝JDK14.0.2的詳細安裝過程的相關資料,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-09-09
  • 使用監(jiān)聽器對Spring bean id進行唯一校驗過程解析

    使用監(jiān)聽器對Spring bean id進行唯一校驗過程解析

    這篇文章主要介紹了使用監(jiān)聽器對Spring bean id進行唯一校驗過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-08-08
  • Java 如何實現(xiàn)解壓縮文件和文件夾

    Java 如何實現(xiàn)解壓縮文件和文件夾

    這篇文章主要介紹了Java 如何實現(xiàn)解壓縮文件和文件夾,幫助大家更好的理解和學習使用Java,感興趣的朋友可以了解下
    2021-03-03
  • token工作機制及原理附Java生成token工具類

    token工作機制及原理附Java生成token工具類

    這篇文章介紹了token工作機制及原理,內附Java生成token工具類Demo。對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-12-12
  • Java爬蟲(Jsoup與WebDriver)的使用

    Java爬蟲(Jsoup與WebDriver)的使用

    這篇文章主要介紹了Java爬蟲(Jsoup與WebDriver)的使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-12-12
  • Java 8 Lambda 表達式比較器使用示例代碼

    Java 8 Lambda 表達式比較器使用示例代碼

    這篇文章主要介紹了Java 8 Lambda 表達式比較器使用示例代碼,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-08-08

最新評論

高台县| 元阳县| 二连浩特市| 明水县| 惠来县| 花垣县| 乡城县| 乌兰察布市| 英山县| 尉氏县| 吴桥县| 宁南县| 灵璧县| 忻州市| 嵩明县| 成武县| 平定县| 沁阳市| 嘉峪关市| 杂多县| 田阳县| 肇源县| 张家口市| 荣昌县| 西宁市| 瓦房店市| 罗平县| 四子王旗| 自治县| 五台县| 鱼台县| 越西县| 和硕县| 太原市| 新野县| 广州市| 大方县| 和政县| 林甸县| 兰州市| 黑龙江省|