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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

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

面向?qū)ο蟮娜齻€特性

面向?qū)ο笥腥齻€重要的特性:多態(tài),繼承,封裝。

多態(tài)的表現(xiàn)

多態(tài)的在java中的應(yīng)用體現(xiàn)在方法的重載和重寫。

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

重寫:對應(yīng)的是子類去重寫了父類的方法,有自己的實現(xiàn),不能更改方法的參數(shù)和名稱。

但是在JVM中是怎么實現(xiàn)的呢?JVM對于這兩種方式是怎么區(qū)分的?

方法的重載

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

執(zhí)行 方法的指令在JVM里面有四個

invokestatic 執(zhí)行靜態(tài)的方法

invokespecial 執(zhí)行構(gòu)造方法,或者調(diào)用父類的方法(對應(yīng)super關(guān)鍵字)

invokedynamic 執(zhí)行動態(tài)語言的方法

invokevirtual 執(zhí)行普通方法

考慮下面代碼

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);

}

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

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

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

它的字節(jié)碼

image.png

但是還有一個點要注意,靜態(tài)類型是可以強轉(zhuǎn)的

public static void main(String args[]){

A a = new A();

B b = new C();

a.print((C)b);

}

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

image.png

方法重載:只會根據(jù)參數(shù)的靜態(tài)類型去匹配。

方法的重寫

方法的重寫:表現(xiàn)的就是重寫父類的方法

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();

}

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

image.png

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

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

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

image.png

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

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

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

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎

總結(jié)

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

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。