亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java中多態(tài)的實現(xiàn)原理詳細解析

 更新時間:2024年01月29日 09:45:22   作者:程序員小玖  
這篇文章主要介紹了Java中多態(tài)的實現(xiàn)原理詳細解析,多態(tài)是面向對象編程語言的重要特性,它允許基類的指針或引用指向派生類的對象,而在具體訪問時實現(xiàn)方法的動態(tài)綁定,需要的朋友可以參考下

Java多態(tài)概述

多態(tài)是面向對象編程語言的重要特性,它允許基類的指針或引用指向派生類的對象,而在具體訪問時實現(xiàn)方法的動態(tài)綁定。

Java 對于方法調用動態(tài)綁定的實現(xiàn)主要依賴于方法表,但通過類引用調用(invokevitual)和接口引用調用(invokeinterface)的實現(xiàn)則有所不同。

類引用調用的大致過程為:Java編譯器將Java源代碼編譯成class文件,在編譯過程中,會根據(jù)靜態(tài)類型將調用的符號引用寫到class文件中。

在執(zhí)行時,JVM根據(jù)class文件找到調用方法的符號引用,然后在靜態(tài)類型的方法表中找到偏移量,然后根據(jù)this指針確定對象的實際類型,使用實際類型的方法表,偏移量跟靜態(tài)類型中方法表的偏移量一樣,如果在實際類型的方法表中找到該方法,則直接調用,否則,認為沒有重寫父類該方法。按照繼承關系從下往上搜索。 

接口引用調用后面再說吧。

從上圖可以看出,當程序運行時,需要某個類時,類載入子系統(tǒng)會將相應的class文件載入到JVM中,并在內部建立該類的類型信息(這個類型信息其實就是class文件在JVM中存儲的一種數(shù)據(jù)結構),包含java類定義的所有信息,包括方法代碼,類變量、成員變量、以及本博文要重點討論的方法表。這個類型信息就存儲在方法區(qū)。 

注意,這個方法區(qū)中的類型信息跟在堆中存放的class對象是不同的。

在方法區(qū)中,這個class的類型信息只有唯一的實例(所以是各個線程共享的內存區(qū)域),而在堆中可以有多個該class對象??梢酝ㄟ^堆中的class對象訪問到方法區(qū)中類型信息。就像在java反射機制那樣,通過class對象可以訪問到該類的所有信息一樣。

重點

方法表是實現(xiàn)動態(tài)調用的核心。上面講過方法表存放在方法區(qū)中的類型信息中。為了優(yōu)化對象調用方法的速度,方法區(qū)的類型信息會增加一個指針,該指針指向一個記錄該類方法的方法表,方法表中的每一個項都是對應方法的指針。 這些方法中包括從父類繼承的所有方法以及自身重寫(override)的方法。

拓展

方法區(qū):方法區(qū)和JAVA堆一樣,是各個線程共享的內存區(qū)域,用于存儲已被虛擬機加載的類信息、常量、靜態(tài)變量、即時編譯器編譯后的代碼等數(shù)據(jù)。  運行時常量池:它是方法區(qū)的一部分,Class文件中除了有類的版本、方法、字段等描述信息外,還有一項信息是常量池,用于存放編譯器生成的各種符號引用,這部分信息在類加載時進入方法區(qū)的運行時常量池中。  方法區(qū)的內存回收目標是針對常量池的回收及對類型的卸載。

Java 的方法調用方式

Java 的方法調用有兩類,動態(tài)方法調用與靜態(tài)方法調用。

靜態(tài)方法調用是指對于類的靜態(tài)方法的調用方式,是靜態(tài)綁定的動態(tài)方法調用需要有方法調用所作用的對象,是動態(tài)綁定的。

類調用 (invokestatic) 是在編譯時就已經(jīng)確定好具體調用方法的情況。

實例調用 (invokevirtual)則是在調用的時候才確定具體的調用方法,這就是動態(tài)綁定,也是多態(tài)要解決的核心問題。

JVM 的方法調用指令有四個,分別是 invokestatic,invokespecial,invokesvirtual 和 invokeinterface。前兩個是靜態(tài)綁定,后兩個是動態(tài)綁定的。本文也可以說是對于JVM后兩種調用實現(xiàn)的考察。

方法表與方法調用

如有類定義 Person, Girl, Boy

class Person {
    public String toString() {
        return "I'm a person.";
    }
    public void eat() {
    }
    public void speak() {
    }
}
class Boy extends Person {
    public String toString() {
        return "I'm a boy";
    }
    public void speak() {
    }
    public void fight() {
    }
}
class Girl extends Person {
    public String toString() {
        return "I'm a girl";
    }
    public void speak() {
    }
    public void sing() {
    }
}

當這三個類被載入到 Java 虛擬機之后,方法區(qū)中就包含了各自的類的信息。Girl 和 Boy 在方法區(qū)中的方法表可表示如下:

可以看到,Girl 和 Boy 的方法表包含繼承自 Object 的方法,繼承自直接父類 Person 的方法及各自新定義的方法。注意方法表條目指向的具體的方法地址,如 Girl 繼承自 Object 的方法中,只有 toString() 指向自己的實現(xiàn)(Girl 的方法代碼),其余皆指向 Object 的方法代碼;其繼承自于 Person 的方法 eat() 和 speak() 分別指向 Person 的方法實現(xiàn)和本身的實現(xiàn)。

如果子類改寫了父類的方法,那么子類和父類的那些同名的方法共享一個方法表項。

因此,方法表的偏移量總是固定的。所有繼承父類的子類的方法表中,其父類所定義的方法的偏移量也總是一個定值。 Person 或 Object中的任意一個方法,在它們的方法表和其子類 Girl 和 Boy 的方法表中的位置 (index) 是一樣的。這樣 JVM 在調用實例方法其實只需要指定調用方法表中的第幾個方法即可。

如調用如下:

class Party {
    void happyHour() {
        Person girl = new Girl();
        girl.speak();
    }
}

當編譯 Party 類的時候,生成 girl.speak()的方法調用假設為:

Invokevirtual #12

設該調用代碼對應著 girl.speak(); #12 是 Party 類的常量池的索引。JVM 執(zhí)行該調用指令的過程如下所示:

(1)在常量池(這里有個錯誤,上圖為ClassReference常量池而非Party的常量池)中找到方法調用的符號引用 。

(2)查看Person的方法表,得到speak方法在該方法表的偏移量(假設為15),這樣就得到該方法的直接引用。 

(3)根據(jù)this指針得到具體的對象(即 girl 所指向的位于堆中的對象)。

(4)根據(jù)對象得到該對象對應的方法表,根據(jù)偏移量15查看有無重寫(override)該方法,如果重寫,則可以直接調用(Girl的方法表的speak項指向自身的方法而非父類);如果沒有重寫,則需要拿到按照繼承關系從下往上的基類(這里是Person類)的方法表,同樣按照這個偏移量15查看有無該方法。

接口調用

因為 Java 類是可以同時實現(xiàn)多個接口的,而當用接口引用調用某個方法的時候,情況就有所不同了。

Java 允許一個類實現(xiàn)多個接口,從某種意義上來說相當于多繼承,這樣同樣的方法在基類和派生類的方法表的位置就可能不一樣了

interface IDance {
    void dance();
}
class Person {
    public String toString() {
        return "I'm a person.";
    }
    public void eat() {
    }
    public void speak() {
    }
}
class Dancer extends Person implements IDance {
    public String toString() {
        return "I'm a dancer.";
    }
    public void dance() {
    }
}
class Snake implements IDance {
    public String toString() {
        return "A snake.";
    }
    public void dance() {
        //snake dance  
    }
}

可以看到,由于接口的介入,繼承自于接口 IDance 的方法 dance()在類 Dancer 和 Snake 的方法表中的位置已經(jīng)不一樣了,顯然我們無法僅根據(jù)偏移量來進行方法的調用。

Java 對于接口方法的調用是采用搜索方法表的方式,如,要在Dancer的方法表中找到dance()方法,必須搜索Dancer的整個方法表。

因為每次接口調用都要搜索方法表,所以從效率上來說,接口方法的調用總是慢于類方法的調用的。

到此這篇關于Java中多態(tài)的實現(xiàn)原理詳細解析的文章就介紹到這了,更多相關Java多態(tài)的實現(xiàn)原理內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 詳解Spring加載Properties配置文件的四種方式

    詳解Spring加載Properties配置文件的四種方式

    這篇文章主要介紹了詳解Spring加載Properties配置文件的四種方式,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-05-05
  • Java繪圖技術的詳解及實例

    Java繪圖技術的詳解及實例

    這篇文章主要介紹了Java繪圖技術的詳解及實例的相關資料,這里主要詳解Graphics類的使用,需要的朋友可以參考下
    2017-08-08
  • java字符串所有操作方法匯總

    java字符串所有操作方法匯總

    這篇文章主要介紹了java字符串所有操作方法匯總,需要的朋友可以參考下,在實際的編程中,我們經(jīng)常需要對字符串進行各種操作,例如連接、截取、替換等,本文將按類別介紹一些Java字符串的常用方法,幫助讀者更好地理解和使用
    2023-11-11
  • Java中List對象集合按對象中某字段進行排序舉例

    Java中List對象集合按對象中某字段進行排序舉例

    這篇文章主要給大家介紹了關于Java中List對象集合按對象中某字段進行排序的相關資料,我們在日常開發(fā)中也經(jīng)常會用到排序算法,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下
    2023-07-07
  • Java中常用加密/解密方法詳解

    Java中常用加密/解密方法詳解

    本文主要介紹了Java中常用加密/解密方法。具有很好的參考價值,下面跟著小編一起來看下吧
    2017-02-02
  • 一步步教你整合SSM框架(Spring MVC+Spring+MyBatis)詳細教程

    一步步教你整合SSM框架(Spring MVC+Spring+MyBatis)詳細教程

    使用SSM(Spring、SpringMVC和Mybatis)已經(jīng)有段時間了,項目在技術上已經(jīng)沒有什么難點了,基于現(xiàn)有的技術就可以實現(xiàn)想要的功能,下面這篇文章主要給大家介紹了關于整合SSM框架:Spring MVC + Spring + MyBatis的相關資料,需要的朋友可以參考下。
    2017-07-07
  • Java?入門圖形用戶界面設計之事件處理下

    Java?入門圖形用戶界面設計之事件處理下

    圖形界面(簡稱GUI)是指采用圖形方式顯示的計算機操作用戶界面。與早期計算機使用的命令行界面相比,圖形界面對于用戶來說在視覺上更易于接受,本篇精講Java語言中關于圖形用戶界面的事件處理
    2022-02-02
  • Java實現(xiàn)后端跨域的常見解決方案

    Java實現(xiàn)后端跨域的常見解決方案

    跨源資源共享(CORS——Cross-Origin Resource Sharing,跨源資源共享,或通俗地譯為跨域資源共享)是一種基于 HTTP 頭的機制,跨域的解決方案有很多種,前后端都有,本文給大家主要介紹Java實現(xiàn)后端跨域的常見解決方案,需要的朋友可以參考下
    2024-04-04
  • 理解Java中的靜態(tài)綁定和動態(tài)綁定

    理解Java中的靜態(tài)綁定和動態(tài)綁定

    這篇文章主要幫助大家理解Java中的靜態(tài)綁定和動態(tài)綁定,在Java中存在兩種綁定方式,一種為靜態(tài)綁定,另一種就是動態(tài)綁定,亦稱為后期綁定,感興趣的小伙伴們可以參考一下
    2016-02-02
  • 使用Feign實現(xiàn)微服務間文件下載

    使用Feign實現(xiàn)微服務間文件下載

    這篇文章主要為大家詳細介紹了使用Feign實現(xiàn)微服務間文件下載,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-04-04

最新評論