JAVA的List介面的remove重載方法調用原理

来源:https://www.cnblogs.com/cartooon/archive/2019/10/09/11645033.html
-Advertisement-
Play Games

前言 說真的,平常看源碼都是自己看完自己懂,很少有寫出來的衝動。 但是在寫演算法的時候,經常用到java中各種集合,其中也比較常用到remove方法。 remove有重載函數,分別傳入參數是索引index或者數據Object(指定泛型後自動轉換),如果指定泛型是其他數據類型還好,但是指定的是Integ ...


前言

說真的,平常看源碼都是自己看完自己懂,很少有寫出來的衝動。
但是在寫演算法的時候,經常用到java中各種集合,其中也比較常用到remove方法。
remove有重載函數,分別傳入參數是索引index或者數據Object(指定泛型後自動轉換),如果指定泛型是其他數據類型還好,但是指定的是Integer或者是int的話,或者就有點懵了。
這曾經也困惑過我,所以我就唯有用實踐解惑了。

測試類設計

  • 測試類一
public class Text {

    public void remove(int index){
        System.out.println("調用傳參為int的remove方法");
    }

    public void remove(Integer object){
        System.out.println("調用傳參為Integer的remove方法");
    }

    public void remove(Object object){
        System.out.println("調用傳參為Object的remove方法");
    }
}
  • 測試類二
public class Text {
    
    public void remove(Integer object){
        System.out.println("調用傳參為Integer的remove方法");
    }

    public void remove(Object object){
        System.out.println("調用傳參為Object的remove方法");
    }
}
  • 測試類三
public class Text {

    public void remove(Object object){
        System.out.println("調用傳參為Object的remove方法");
    }
}

結果

三個測試類分別傳入int,Integer,Object型變數,觀察效果。

  • 測試類一

    傳入類型為int:調用傳參為int的remove方法
    傳入類型為Integer:調用傳參為Integer的remove方法
    傳入類型為Object:調用傳參為Object的remove方法

  • 測試類二

    傳入類型為int:調用傳參為Integer的remove方法
    傳入類型為Integer:調用傳參為Integer的remove方法
    傳入類型為Object:調用傳參為Object的remove方法

  • 測試類三

    傳入類型為int:調用傳參為Object的remove方法
    傳入類型為Integer:調用傳參為Object的remove方法
    傳入類型為Object:調用傳參為Object的remove方法

從輸出結果可以看出,當方法的傳參的類層級逐漸變高時,層級較低的傳參會進行向上轉型適應傳參的需要。

原因分析

下麵我們先反編譯各測試類的源碼,結果如下

  • 測試類一

    invokevirtual #11 // Method remove:(I)V

    invokevirtual #15 // Method remove:(Ljava/lang/Integer;)V

    invokevirtual #18 // Method remove:(Ljava/lang/Object;)V

  • 測試類二

    invokevirtual #11 // Method remove:(Ljava/lang/Integer;)V

    invokevirtual #11 // Method remove:(Ljava/lang/Integer;)V

    invokevirtual #17 // Method remove:(Ljava/lang/Object;)V

  • 測試類三

    invokevirtual #10 // Method remove:(Ljava/lang/Object;)V

    invokevirtual #10 // Method remove:(Ljava/lang/Object;)V

    invokevirtual #10 // Method remove:(Ljava/lang/Object;)V

可以看出,反編譯代碼中都是調用實例方法的命令,所以結果中自動"向上轉型"其實是jvm的功勞。jvm通過在編譯時確定調用的傳參類型,靜態分派到具體方法的。
所以在前言中的困惑已經解除了,就是由於jvm中靜態分派的實現,調用次序是int->Integer->Object。

後記

也沒什麼想說的,感覺在閱讀源碼的時候必須多想想為什麼這樣做,為什麼要這樣實現,同時通過斷點或者反編譯的手段找出自己的答案。keep going!

本文首發於cartoon的博客
轉載請註明出處:https://cartoonyu.github.io/cartoon-blog/post/java/java的list介面的remove重載方法調用原理/


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、楔子 你現在已經學會了寫python代碼,假如你寫了兩個python文件a.py和b.py,分別去運行,你就會發現,這兩個python的文件分別運行的很好。但是如果這兩個程式之間想要傳遞一個數據,你要怎麼做呢? 這個問題以你現在的知識就可以解決了,我們可以創建一個文件,把a.py想要傳遞的內容寫 ...
  • ① 向資料庫發送SQL查詢語句 首先使用Statement聲明一個SQL語句對象,然後讓已創建的連接對象con調用方法createStatement()創建SQL語句對象。 Statement sql = con.createStatement(); Connection con = null; S ...
  • 一、主方法註意 每一個類都可以編寫一個主方法,但是一般情況下,一個系統只有一個入口,所以主方法一般寫一個 二、Myeclipse的使用 1.在workspace中工作區中有一個文件夾.metadata:在該文件夾中存儲了當前MyEclipse的工作狀態 2.將.metadata文件夾刪除之後,下一次 ...
  • 本系列文章將整理到我在GitHub上的《Java面試指南》倉庫,更多精彩內容請到我的倉庫里查看 https://github.com/h2pl/Java Tutorial 喜歡的話麻煩點下Star哈 文章首發於我的個人博客: www.how2playlife.com <! more 從JVM結構開始 ...
  • 本系列文章將整理到我在GitHub上的《Java面試指南》倉庫,更多精彩內容請到我的倉庫里查看 https://github.com/h2pl/Java Tutorial 喜歡的話麻煩點下Star哈 文章首發於我的個人博客: www.how2playlife.com <! more 本文參考 htt ...
  • 本文的記憶體模型只寫虛擬機記憶體模型,物理機的不予描述。 Java記憶體模型 在Java中,虛擬機將運行時區域分成6中,如下圖: 由於類和方法的信息難以確定,不好設定大小,太大則影響年老代,太小容易記憶體溢出。 GC不好處理,回收效率低下,調優困難。 在上面的6種類型中,前三種是線程私有的,也就是說裡面存放 ...
  • 本系列文章將整理到我在GitHub上的《Java面試指南》倉庫,更多精彩內容請到我的倉庫里查看 https://github.com/h2pl/Java Tutorial 喜歡的話麻煩點下Star哈 文章首發於我的個人博客: www.how2playlife.com <! more 這是一個Java ...
  • 類型關係 Scala 支持在泛型類上使用型變註釋,用來表示覆雜類型、組合類型的子類型關係間的相關性 協變 ,變化方向相同,通常用在生產 假設 , 對於 ,則 也可看做 由於 Scala 標準庫中不可變 的定義為 ,因此 是 的子類型, 也是 的子類型,所以可直接將他們當作 使用。 逆變 ,變化方向相 ...
一周排行
    -Advertisement-
    Play Games
  • 前言 插件化的需求主要源於對軟體架構靈活性的追求,特別是在開發大型、複雜或需要不斷更新的軟體系統時,插件化可以提高軟體系統的可擴展性、可定製性、隔離性、安全性、可維護性、模塊化、易於升級和更新以及支持第三方開發等方面的能力,從而滿足不斷變化的業務需求和技術挑戰。 一、插件化探索 在WPF中我們想要開 ...
  • 歡迎ReaLTaiizor是一個用戶友好的、以設計為中心的.NET WinForms項目控制項庫,包含廣泛的組件。您可以使用不同的主題選項對項目進行個性化設置,並自定義用戶控制項,以使您的應用程式更加專業。 項目地址:https://github.com/Taiizor/ReaLTaiizor 步驟1: ...
  • EDP是一套集組織架構,許可權框架【功能許可權,操作許可權,數據訪問許可權,WebApi許可權】,自動化日誌,動態Interface,WebApi管理等基礎功能於一體的,基於.net的企業應用開發框架。通過友好的編碼方式實現數據行、列許可權的管控。 ...
  • Channel 是乾什麼的 The System.Threading.Channels namespace provides a set of synchronization data structures for passing data between producers and consume ...
  • efcore如何優雅的實現按年分庫按月分表 介紹 本文ShardinfCore版本 本期主角: ShardingCore 一款ef-core下高性能、輕量級針對分表分庫讀寫分離的解決方案,具有零依賴、零學習成本、零業務代碼入侵適配 距離上次發文.net相關的已經有很久了,期間一直在從事java相關的 ...
  • 前言 Spacesniffer 是一個免費的文件掃描工具,通過使用樹狀圖可視化佈局,可以立即瞭解大文件夾的位置,幫助用戶處理找到這些文件夾 當前系統C盤空間 清理後系統C盤空間 下載 Spacesniffer 下載地址:https://spacesniffer.en.softonic.com/dow ...
  • EDP是一套集組織架構,許可權框架【功能許可權,操作許可權,數據訪問許可權,WebApi許可權】,自動化日誌,動態Interface,WebApi管理等基礎功能於一體的,基於.net的企業應用開發框架。通過友好的編碼方式實現數據行、列許可權的管控。 ...
  • 一、ReZero簡介 ReZero是一款.NET中間件 : 全網唯一開源界面操作就能生成API , 可以集成到任何.NET6+ API項目,無破壞性,也可讓非.NET用戶使用exe文件 免費開源:MIT最寬鬆協議 , 一直從事開源事業十年,一直堅持開源 1.1 純ReZero開發 適合.Net Co ...
  • 一:背景 1. 講故事 停了一個月沒有更新文章了,主要是忙於寫 C#內功修煉系列的PPT,現在基本上接近尾聲,可以回頭繼續更新這段時間分析dump的一些事故報告,有朋友微信上找到我,說他們的系統出現了大量的http超時,程式不響應處理了,讓我幫忙看下怎麼回事,dump也抓到了。 二:WinDbg分析 ...
  • 開始做項目管理了(本人3年java,來到這邊之後真沒想到...),天天開會溝通整理需求,他們講話的時候忙裡偷閑整理一下常用的方法,其實語言還是有共通性的,基本上看到方法名就大概能猜出來用法。出去打水的時候看到外面太陽好好,真想在外面坐著曬太陽,回來的時候好兄弟三年前送給我的鍵盤D鍵不靈了,在打"等待 ...