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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

java 重载 不可_深入深刻深到不能再深的理解java中的重载和重写

發布時間:2023/12/15 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 重载 不可_深入深刻深到不能再深的理解java中的重载和重写 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

面向對象的三個特性

面向對象有三個重要的特性:多態,繼承,封裝。

多態的表現

多態的在java中的應用體現在方法的重載和重寫。

重載:字面上的意義一個類里面,有同名但是參數必須不相同的方法。(這里的”不同參數“必須不是泛型,比如List 和List)

重寫:對應的是子類去重寫了父類的方法,有自己的實現,不能更改方法的參數和名稱。

但是在JVM中是怎么實現的呢?JVM對于這兩種方式是怎么區分的?

方法的重載

我們都知道,.java的源文件都會被編譯成.class的文件,class文件是一堆二進制流。

執行 方法的指令在JVM里面有四個

invokestatic 執行靜態的方法

invokespecial 執行構造方法,或者調用父類的方法(對應super關鍵字)

invokedynamic 執行動態語言的方法

invokevirtual 執行普通方法

考慮下面代碼

class A{

pulic void print(B b){

}

pulic void print(C c){

}

}

public static void main(String args[]){

A a = new A();

B b = new C();

a.print(b);

}

當我們調用 a.print(b)的時候,虛擬機會根據你傳遞參數的靜態類型去匹配方法,這是一個靜態分派的過程。

什么叫靜態類型 比如 B b = new C();C是派生B的,我們經常在java中這么寫,沒有任何問題。這里對象B的靜態類型就是B,但是它的實際類型是C。

我們調用a.print(b)的時候它匹配的是 print(B b)這個方法,所以編譯器它不會考慮這個b的實際類型(因為B的實際類型會被執行invospecial去指定)是什么,它直接在編譯成字節碼階段就把這個方法匹配了。

它的字節碼

image.png

但是還有一個點要注意,靜態類型是可以強轉的

public static void main(String args[]){

A a = new A();

B b = new C();

a.print((C)b);

}

這時候它匹配的就是print(C c)這個方法了

image.png

方法重載:只會根據參數的靜態類型去匹配。

方法的重寫

方法的重寫:表現的就是重寫父類的方法

public class B {

public void callMe(){

System.out.print("B is call");

}

}

public class C extends B {

@Override

public void callMe() {

System.out.print("C is call");

}

}

public static void main(String args[]){

B b = new B();

b.callMe();

B c = new C();

c.callMe();

}

在編譯階段它只會在靜態類型中去匹配方法,所以盡管b和c 的實際類型不同,但它們執行callMe的字節碼指令是相同的

image.png

但是虛擬機在執行這個指令的時候,它會先在操作數棧中拿到調用這個方法的對象,然后根據這個對象的實際類型去匹配方法,如果這個類型里面沒有,則它就會去父類去找一直遞歸直到找到為止。否則將會拋出MethodNotFoundException。

這樣遞歸非常麻煩,所以虛擬機會對每一個clas對象都生成一個方法表。(這個在連接階段會準備好,一般再類變量初始為零值之后)

它里面保存了這個類所有方法直接引用(也是就能再虛擬機中找到執行的代碼),保存的順序先是父類的方法,然后才是自己的方法,如果子類重寫了父類的方法,它會將這個指針指向自己的實現,否則指向父類,這樣的好處是只用查找一次,不管類型怎么切換,只要他們的方法表的順序是一致的,我就可以根據這個下標去找到對應的方法入口。

image.png

比如使用son的對象 son.hardChoice(),會再son的方法表里面找到方法入口,虛擬機會記住這個下標,當我再使用

father.hardChoice()的時候,直接切換到Father的方法表,通過記住的這個下標找到方法入口,不用去遍歷了!

同理接口也有對應的接口表,它里面的方法就是無序的了,無法通過下標去查找,每一次調用方法都只能去遍歷整個表,所以一般來說查找接口方法比查找普通方法要慢。

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的java 重载 不可_深入深刻深到不能再深的理解java中的重载和重写的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。