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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

分派

發布時間:2024/2/28 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 分派 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

靜態分派和動態分派

靜態分派案例:

public class fenpai {static abstract class A {}static class B extends A {}static class C extends A {} public static void sayHi(A a) {System.out.println("hi ,father");}public void sayHi(B b) {System.out.println("hi ,sister");}public void sayHi(C c) {System.out.println("hi ,brother");}public static void main(String[] args) {fenpai f = new fenpai();A a1 = new B();A a2 = new C();f.sayHi(a1);f.sayHi(a2);} } hi ,father hi ,father

?

動態分派案例:

public class fenpai {static abstract class A {public void sayHi() {System.out.println("hi ,father");}}static class B extends A {@Overridepublic void sayHi() {System.out.println("hi ,father");}}static class C extends A {@Overridepublic void sayHi() {System.out.println("hi ,sister");}} public void sayHi(C c) {System.out.println("hi ,brother");}public static void main(String[] args) {fenpai f = new fenpai();A a1 = new B();A a2 = new C();a1.sayHi();a2.sayHi();} } hi ,father hi ,sister

解釋一下兩種結果不同的原因:
父類A稱為變量的靜態類型,也叫外觀類型,子類BC稱為實際類型,靜態類型是編譯期可知的,而實際類型是運行期才知道。

結果不同的原因是:

  • 靜態分配的虛擬機重載時,是通過參數的靜態類型而不是實際類型進行判定的,編譯器在編譯階段,直接根據靜態類型決定使用哪個版本。
  • 而動態分配是方法的重寫,Java虛擬機是通過實際類型來判斷執行的版本。

讓我們來看一下他們的二進制字節碼來了解編譯器干了什么?
?

靜態分配

public static void main(java.lang.String[]);descriptor: ([Ljava/lang/String;)Vflags: ACC_PUBLIC, ACC_STATICCode:stack=2, locals=4, args_size=10: new #1 // class fenpai3: dup4: invokespecial #44 // Method "<init>":()V7: astore_18: new #45 // class fenpai$B11: dup12: invokespecial #47 // Method fenpai$B."<init>":()V15: astore_216: new #48 // class fenpai$C19: dup20: invokespecial #50 // Method fenpai$C."<init>":()V23: astore_324: aload_225: invokestatic #51 // Method sayHi:(Lfenpai$A;)V28: aload_329: invokestatic #51 // Method sayHi:(Lfenpai$A;)V32: returnLineNumberTable:line 24: 0line 25: 8line 26: 16line 27: 24line 28: 28line 29: 32LocalVariableTa

動態分配

public static void main(java.lang.String[]);descriptor: ([Ljava/lang/String;)Vflags: ACC_PUBLIC, ACC_STATICCode:stack=2, locals=4, args_size=10: new #1 // class fenpai3: dup4: invokespecial #34 // Method "<init>":()V7: astore_18: new #35 // class fenpai$B11: dup12: invokespecial #37 // Method fenpai$B."<init>":()V15: astore_216: new #38 // class fenpai$C19: dup20: invokespecial #40 // Method fenpai$C."<init>":()V23: astore_324: aload_225: invokevirtual #41 // Method fenpai$A.sayHi:()V28: aload_329: invokevirtual #41 // Method fenpai$A.sayHi:()V32: returnLineNumberTable:line 28: 0line 29: 8line 30: 16line 31: 24line 32: 28line 33: 32

很清楚地看到靜態分配的25行 29行invokestatic
動態分配的25行,29行invokevirtual
這就是區別所在。
a)靜態分配在編譯器就決定了使用哪個重載版本,所以他把這個決定的重載方法寫入了invokestatic指令中。
b)動態分配,編譯器不知道實際類型,所以他不知道執行哪個重寫版本,于是它只能寫入invokevirtual指令中。

invokevirtual指令執行過程:
1)確定接受者的實際類型。
2)在操作數棧找到對應這個實際類型。
3)在類型中找到與常量中描述符合和簡單名稱都相同的方法,進行訪問權限檢驗,如果通過,則返回這個方法的直接引用,如果不通過,返回java.lang.IllegalAccessError 異常。
4)否則,按照繼承關系從上往下對這個實際類型的各個父類進行第三步的搜索和驗證功能。
5)如果沒有合適的方法,則拋出java.lang.AbstractMethodError。

總結

以上是生活随笔為你收集整理的分派的全部內容,希望文章能夠幫你解決所遇到的問題。

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