大战熟女丰满人妻av-荡女精品导航-岛国aaaa级午夜福利片-岛国av动作片在线观看-岛国av无码免费无禁网站-岛国大片激情做爰视频

專注Java教育14年 全國咨詢/投訴熱線:400-8080-105
動力節點LOGO圖
始于2009,口口相傳的Java黃埔軍校
首頁 學習攻略 Java學習 Java基礎學習:java方法調用

Java基礎學習:java方法調用

更新時間:2020-04-23 14:36:27 來源:動力節點 瀏覽2365次

方法調用并不等同于方法中的代碼被執行,方法調用階段唯一的任務就是確定被調用方法的版本(即調用哪一個方法),暫時還未涉及方法內部的具體運行過程。一切方法調用在Class文件里面存儲的都只是符號引用,而不是方法在實際運行時內存布局中的入口地址(也就是之前說的直接引用)。

Java基礎學習:java方法調用

解析

所有方法調用的目標方法在Class文件里面都是一個常量池中的符號引用,在類加載的解析階段,會將其中的一部分符號引用轉化為直接引用,這種解析能夠成立的前提是:方法在程序真正運行之前就有一個可確定的調用版本,并且這個方法的調用版本在運行期是不可改變的。換句話說,調用目標在程序代碼寫好、編譯器進行編譯那一刻就已經確定下來。這類方法的調用被稱為解析(Resolution),在Java語言中符合這種要求的主要有靜態方法和私有方法。

方法調用指令

invokestatic:用于調用靜態方法。

invokespecial:用于調用實例構造器<init>()方法、私有方法和父類中的方法。

invokevirtual:用于調用所有的虛方法。

invokeinterface:用于調用接口方法,會在運行時再確定一個實現該接口的對象。

invokedynamic:先在運行時動態解析出調用點限定符所引用的方法,然后再執行該方法。

前面4條調用指令,分派邏輯都固化在Java虛擬機內部,而invokedynamic指令的分派邏輯是由用戶設定的引導方法來決定的。

方法分類

在java語言中方法主要分為“虛方法”和“非虛方法”。

非虛方法:在類加載的時候就可以把符號引用解析為該方法的直接引用。比如:靜態方法、私有方法、實例構造器、父類方法和被final修飾的方法。

虛方法:需要在運行時才能將符號引用轉換成直接引用,如,分派。

分派

分派(Dispatch)它可能是靜態的也可能是動態的,按照分派依據的宗量數可分為單分派和多分派。這兩類分派方式兩兩組合就構成了靜態單分派、靜態多分派、動態單分派、動態多分派4種分派組合情況。

靜態分派

依賴靜態類型來決定方法執行版本的分派動作,都稱為靜態分派。靜態分派的最典型應用表現就是方法重載,虛擬機(或者準確地說是編譯器)在重載時是通過參數的靜態類型來作為判定依據的。 

public class StaticDispatch{
static abstract class Human{
}
static class Man extends Human{
}
static class Woman extends Human{
}
public void sayHello(Human guy){
System.out.println("hello,guy!");
}
public void sayHello(Man guy){
System.out.println("hello,gentleman!");
}
public void sayHello(Woman guy){
System.out.println("hello,lady!");
}
public static void main(String[]args){
Human man=new Man();
Human woman=new Woman();
StaticDispatch sr=new StaticDispatch();
sr.sayHello(man);
sr.sayHello(woman);
}
}

運行結果:
hello,guy!
hello,guy!
Human man=new Man();

這里的Human就是變量的“靜態類型”(Static Type),或者叫“外觀類型”(Apparent Type);Man就是變量的“實際類型”(Actual Type)或者叫“運行時類型”(Runtime Type)。

動態分派

我們把在運行期根據實際類型確定方法執行版本的分派過程稱為動態分派。最典型的表現就是重寫。

public class DynamicDispatch{
static abstract class Human{
abstract void sayHello();
}

static class Man extends Human{
public void sayHello(){
System.out.println("hello,Man!");
}
}

static class Woman extends Human{
public void sayHello(){
System.out.println("hello,Woman!");
}
}

public static void main(String[]args){
Human man=new Man();
Human woman=new Woman();
man.sayHello();
woman.sayHello();
}
}

運行結果:
hello,Man!
hello,Woman!

我們通過javap命令看下main方法的字節碼:  

...
public static void main(java.lang.String[]);
descriptor:([Ljava/lang/String;)V
flags:ACC_PUBLIC,ACC_STATIC
Code:
stack=2,locals=3,args_size=1

0:new
3:dup
4:invokespecial
7:astore_1
8:new
12:invokespecial
15:astore_2
16:aload_1
17:invokevirtual
20:aload_2
21:invokevirtual
24:return
LineNumberTable:
line 27:0
line 28:8
line 29:16
line 30:20
line 31:24
LocalVariableTable:
Start Length Slot Name Signature
0 25 0 args[Ljava/lang/String;
8 17 1 man Lcom/xiaolyuh/DynamicDispatch$Human;
16 9 2 woman Lcom/xiaolyuh/DynamicDispatch$Human;
}
...

通過字節碼我們發現:在main方法中,sayHello()方法的調用對應的符號引用是一樣的,com/xiaolyuh/DynamicDispatch$Human.sayHello:()V。在這里我們可以得出一個結論:在動態分派的情況下,在編譯時期我們是無法確定方法的直接引用的,那么它是怎么實現重載方法的調用的呢?問題關鍵是在invokevirtual指令上,在執行invokevirtual指令時,invokevirtual指令會去確定方法的調用版本。

Java基礎學習:java方法調用

以上就是動力節點java培訓機構的小編針對“Java基礎學習:java方法調用”的內容進行的回答,希望對大家有所幫助,如有疑問,請在線咨詢,有專業老師隨時為你服務。

提交申請后,顧問老師會電話與您溝通安排學習

免費課程推薦 >>
技術文檔推薦 >>
主站蜘蛛池模板: 久久久久久久国产精品 | 国产精品va一区二区三区 | 亚洲最大在线 | 国产高清精品久久久久久久 | 国产精品视频一区二区三区不卡 | 久久99热精品免费观看无卡顿 | 亚洲天天综合 | 手机看片神马午夜片 | 91国内视频在线观看 | 久久天天躁狠狠躁夜夜躁 | 四虎免费看黄 | 久久99久久精品国产只有 | 性欧美video视频另类 | 国产精品国偷自产在线 | 色综合亚洲综合网站综合色 | 日本伦理中文字幕 | 成年人性生活免费视频 | 99精品国产一区二区青青牛奶 | 91久久老司机福利精品网 | 亚洲欧美另类国产综合 | a一级毛片免费高清在线 | www黄在线观看 | 特级aaa毛片| 国产亚洲欧美日韩综合综合二区 | 伊人婷婷色 | 成年女人毛片免费观看中文w | 国产成人18黄网站麻豆 | 亚洲国产日韩综合久久精品 | 国产免费资源 | 欧美激情在线播放 | 男人的天堂视频在线 | 国产一二三区在线观看 | 久久精品综合网 | 国产精品久久久久久久午夜片 | 狠狠色噜噜狠狠狠狠97不卡 | 欧美视频在线视频 | 视频播放在线观看精品视频 | 国产网红自拍 | 日韩国产欧美一区二区三区在线 | 天天射夜夜爱 | 国产精品亚洲精品久久成人 |