最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java如何對(duì)方法進(jìn)行調(diào)用詳解

 更新時(shí)間:2021年06月02日 14:49:39   作者:Tc.l  
今天給大家整理了Java如何對(duì)方法進(jìn)行調(diào)用,文中有非常詳細(xì)的介紹及代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們很有幫助,需要的朋友可以參考下

一、方法調(diào)用

方法調(diào)用的唯一目的:確定要調(diào)用哪一個(gè)方法

方法調(diào)用分為解析調(diào)用和分派調(diào)用

二、非虛方法與虛方法

非虛方法: 靜態(tài)方法,私有方法,父類中的方法,被final修飾的方法,實(shí)例構(gòu)造器

與之對(duì)應(yīng)不是非虛方法的就是虛方法了

它們都沒(méi)有重寫出其他版本的方法,非常適合在類加載階段就進(jìn)行解析(符號(hào)引用->直接引用)

三、調(diào)用指令

普通調(diào)用指令

  • invokestatic:調(diào)用靜態(tài)方法
  • invokespecial:調(diào)用私有方法,父類中的方法,實(shí)例構(gòu)造器方法,final方法
  • invokeinterface:調(diào)用接口方法
  • invokevirtual: 調(diào)用虛方法

使用invokestaticinvokespecial指令的一定是非虛方法

使用invokeinterface指令一定是虛方法(因?yàn)榻涌诜椒ㄐ枰唧w的實(shí)現(xiàn)類去實(shí)現(xiàn))

使用invokevirtual指令的是虛方法

動(dòng)態(tài)調(diào)用指令

invokedynamic: 動(dòng)態(tài)解析出需要調(diào)用的方法再執(zhí)行

jdk 7 出現(xiàn)invokedynamic,支持動(dòng)態(tài)語(yǔ)言

測(cè)試虛方法代碼

父類

public class Father {
    public static void staticMethod(){
        System.out.println("father static method");
    }

    public final void finalMethod(){
        System.out.println("father final method");
    }

    public Father() {
        System.out.println("father init method");
    }

    public void overrideMethod(){
        System.out.println("father override method");
    }
}

接口

public interface TestInterfaceMethod {
    void testInterfaceMethod();
}

子類

public class Son extends Father{

    public Son() {
        //invokespecial 調(diào)用父類init 非虛方法
        super();
        //invokestatic 調(diào)用父類靜態(tài)方法 非虛方法
        staticMethod();
        //invokespecial 調(diào)用子類私有方法 特殊的非虛方法
        privateMethod();
        //invokevirtual 調(diào)用子類的重寫方法 虛方法
        overrideMethod();
        //invokespecial 調(diào)用父類方法 非虛方法
        super.overrideMethod();
        //invokespecial 調(diào)用父類final方法 非虛方法
        super.finalMethod();
        //invokedynamic 動(dòng)態(tài)生成接口的實(shí)現(xiàn)類 動(dòng)態(tài)調(diào)用
        TestInterfaceMethod test = ()->{
            System.out.println("testInterfaceMethod");
        };
        //invokeinterface 調(diào)用接口方法 虛方法
        test.testInterfaceMethod();
    }

    @Override
    public void overrideMethod(){
        System.out.println("son override method");
    }

    private void privateMethod(){
        System.out.println("son private method");
    }

    public static void main(String[] args) {
        new Son();
    }
}

注意: 接口中的默認(rèn)方法也是invokeinterface,接口中的靜態(tài)方法是invokestatic

四、解析調(diào)用

在編譯就確定了要調(diào)用哪個(gè)方法,運(yùn)行時(shí)不可以改變

解析調(diào)用 調(diào)用的是 非虛方法

五、分派調(diào)用

分派又分為靜態(tài)分派與動(dòng)態(tài)分配

早期綁定:解析調(diào)用和靜態(tài)分派這種編譯期間可以確定調(diào)用哪個(gè)方法

晚期綁定: 動(dòng)態(tài)分派這種編譯期無(wú)法確定,要到運(yùn)行時(shí)才能確定調(diào)用哪個(gè)方法

六、靜態(tài)分派

//  靜態(tài)類型      	 實(shí)際類型
	List list = new ArrayList();

靜態(tài)分派: 根據(jù)靜態(tài)類型決定方法執(zhí)行的版本的分派

發(fā)生在編譯期,特殊的解析調(diào)用

典型的表現(xiàn)就是方法的重載

public class StaticDispatch {
    public void test(List list){
        System.out.println("list");
    }

    public void test(ArrayList arrayList){
        System.out.println("arrayList");
    }

    public static void main(String[] args) {
        ArrayList arrayList = new ArrayList();
        List list = new ArrayList();
        StaticDispatch staticDispatch = new StaticDispatch();
        staticDispatch.test(list);
        staticDispatch.test(arrayList);
    }
}
/*
list
arrayList
*/

方法的版本并不是唯一的,往往只能確定一個(gè)最適合的版本

七、動(dòng)態(tài)分派

動(dòng)態(tài)分派:動(dòng)態(tài)期根據(jù)實(shí)際類型確定方法執(zhí)行版本的分派

動(dòng)態(tài)分派與重寫有著緊密的聯(lián)系

public class DynamicDispatch {
    public static void main(String[] args) {
        Father father = new Father();
        Father son = new Son();

        father.hello();
        son.hello();
    }
    static class Father{
        public void hello(){
            System.out.println("Father hello");
        }
    }

    static class Son extends Father{
        @Override
        public void hello() {
            System.out.println("Son hello");
        }
    }
}
/*
Father hello
Son hello
*/

雖然常量池中的符號(hào)引用相同,invokevirtual指令最終指向的方法卻不一樣

分析invokevirtual指令搞懂它是如何確定調(diào)用的方法

1.invokevirtual找到棧頂元素的實(shí)際類型

2.如果在這個(gè)實(shí)際類型中找到與常量池中描述符與簡(jiǎn)單名稱相符的方法,并通過(guò)訪問(wèn)權(quán)限的驗(yàn)證就返回這個(gè)方法的引用(未通過(guò)權(quán)限驗(yàn)證返回IllegalAccessException非法訪問(wèn)異常)

3.如果在實(shí)際類型中未找到,就去實(shí)際類型的父類中尋找(沒(méi)找到拋出AbstractMethodError異常)

因此,子類重寫父類方法時(shí),根據(jù)invokevirtual指令規(guī)則,先找實(shí)際類型,所以才存在重寫的多態(tài)

頻繁的動(dòng)態(tài)分派會(huì)重新查找棧頂元素實(shí)際類型,會(huì)影響執(zhí)行效率

為提高性能,JVM在該類方法區(qū)建立虛方法表使用索引表來(lái)代替查找

字段不存在多態(tài)

當(dāng)子類出現(xiàn)與父類相同的字段,子類會(huì)覆蓋父類的字段

public class DynamicDispatch {
    public static void main(String[] args) {
        Father son = new Son();
    }
    static class Father{
        int num = 1;

        public Father() {
            hello();
        }

        public void hello(){
            System.out.println("Father hello " + num);
        }
    }

    static class Son extends Father{
        int num = 2;

        public Son() {
            hello();
        }

        @Override
        public void hello() {
            System.out.println("Son hello "+ num);
        }
    }
}
/*
Son hello 0
Son hello 2
*/

先對(duì)父類進(jìn)行初始化,所以會(huì)先執(zhí)行父類中的構(gòu)造方法,而構(gòu)造方法去執(zhí)行了hello()方法,此時(shí)的實(shí)際類型是Son于是會(huì)去執(zhí)行Son的hello方法,此時(shí)子類還未初始化成員變量,只是有個(gè)默認(rèn)值,所以輸出Son hello 0

八、單分派與多分派

public class DynamicDispatch {
    public static void main(String[] args) {
        Father son = new Son();
        Father father = new Father();

        son.hello(new Nod());
        father.hello(new Wave());
    }
    static class Father{


        public void hello(Nod nod){
            System.out.println("Father nod hello " );
        }

        public void hello(Wave wave){
            System.out.println("Father wave hello " );
        }
    }

    static class Son extends Father{

        @Override
        public void hello(Nod nod) {
            System.out.println("Son nod hello");
        }

        @Override
        public void hello(Wave wave) {
            System.out.println("Son wave hello");
        }
    }

    //招手
    static class Wave{}
    //點(diǎn)頭
    static class Nod{}
}
/*
Son nod hello
Father wave hello 
*/

宗量: 方法參數(shù)與方法調(diào)用者

分派還可以分為單,多分派

單分派:根據(jù)一個(gè)宗量選擇方法

多分派:根據(jù)多個(gè)宗量選擇方法

在編譯時(shí),不僅要關(guān)心靜態(tài)類型是Father還是Son,還要關(guān)心參數(shù)是Nod還是Wave,所以靜態(tài)分派是多分派(根據(jù)兩個(gè)宗量對(duì)方法進(jìn)行選擇)

在執(zhí)行son.hello(new Nod())時(shí)只需要關(guān)心實(shí)際類型是Son還是Father,所以動(dòng)態(tài)分派是單分派(根據(jù)一個(gè)宗量對(duì)方法進(jìn)行選擇)

到此這篇關(guān)于Java如何對(duì)方法進(jìn)行調(diào)用詳解的文章就介紹到這了,更多相關(guān)Java調(diào)用方法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • springboot整合minio實(shí)現(xiàn)文件存儲(chǔ)功能

    springboot整合minio實(shí)現(xiàn)文件存儲(chǔ)功能

    MinIO?是一個(gè)基于Apache?License?v2.0開源協(xié)議的對(duì)象存儲(chǔ)服務(wù),它兼容亞馬遜S3云存儲(chǔ)服務(wù)接口,非常適合于存儲(chǔ)大容量非結(jié)構(gòu)化的數(shù)據(jù),本文給大家介紹了springboot整合minio實(shí)現(xiàn)文件存儲(chǔ)功能,文中通過(guò)代碼示例介紹的非常詳細(xì),需要的朋友可以參考下
    2023-12-12
  • IntelliJ IDEA創(chuàng)建maven多模塊項(xiàng)目(圖文教程)

    IntelliJ IDEA創(chuàng)建maven多模塊項(xiàng)目(圖文教程)

    這篇文章主要介紹了IntelliJ IDEA創(chuàng)建maven多模塊項(xiàng)目(圖文教程),非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2017-09-09
  • Java中使用SQLite數(shù)據(jù)庫(kù)的實(shí)現(xiàn)示例

    Java中使用SQLite數(shù)據(jù)庫(kù)的實(shí)現(xiàn)示例

    SQLite是一種嵌入式數(shù)據(jù)庫(kù)引擎,可以在各種平臺(tái)上使用,本文主要介紹了Java中使用SQLite數(shù)據(jù)庫(kù)的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01
  • hibernate5.2的基本配置方法(詳解)

    hibernate5.2的基本配置方法(詳解)

    下面小編就為大家?guī)?lái)一篇hibernate5.2的基本配置方法(詳解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-06-06
  • Spring web集成rabbitmq代碼實(shí)例

    Spring web集成rabbitmq代碼實(shí)例

    這篇文章主要介紹了Spring web集成rabbitmq代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-01-01
  • Java中的LinkedHashSet源碼解讀

    Java中的LinkedHashSet源碼解讀

    這篇文章主要介紹了Java中的LinkedHashSet源碼解讀,LinkedHashSet?是?Java?中的一個(gè)集合類,它是?HashSet?的子類,并實(shí)現(xiàn)了?Set?接口,與?HashSet?不同的是,LinkedHashSet?保留了元素插入的順序,并且具有?HashSet?的快速查找特性,需要的朋友可以參考下
    2023-09-09
  • 零基礎(chǔ)入門SpringMVC攔截器的配置與使用

    零基礎(chǔ)入門SpringMVC攔截器的配置與使用

    Spring?MVC?的攔截器(Interceptor)與?Java?Servlet?的過(guò)濾器(Filter)類似,它主要用于攔截用戶的請(qǐng)求并做相應(yīng)的處理,通常應(yīng)用在權(quán)限驗(yàn)證、記錄請(qǐng)求信息的日志、判斷用戶是否登錄等功能上。本文將代碼演示和文字描述詳解攔截器的原理與使用
    2022-04-04
  • JAVA 創(chuàng)建線程池的注意事項(xiàng)

    JAVA 創(chuàng)建線程池的注意事項(xiàng)

    這篇文章主要介紹了JAVA 創(chuàng)建線程池的注意事項(xiàng),文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • 30分鐘入門Java8之默認(rèn)方法和靜態(tài)接口方法學(xué)習(xí)

    30分鐘入門Java8之默認(rèn)方法和靜態(tài)接口方法學(xué)習(xí)

    這篇文章主要介紹了30分鐘入門Java8之默認(rèn)方法和靜態(tài)接口方法學(xué)習(xí),詳細(xì)介紹了默認(rèn)方法和接口,有興趣的可以了解一下。
    2017-04-04
  • Java代碼里如何拼接SQL語(yǔ)句到mybatis的xml

    Java代碼里如何拼接SQL語(yǔ)句到mybatis的xml

    這篇文章主要介紹了Java代碼里拼接SQL語(yǔ)句到mybatis的xml操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06

最新評(píng)論

恩施市| 崇明县| 永昌县| 正安县| 梅州市| 富民县| 吴江市| 南澳县| 巴彦淖尔市| 青阳县| 夹江县| 南漳县| 金平| 田阳县| 平武县| 米泉市| 吴桥县| 大埔区| 页游| 荣昌县| 奉节县| 潞西市| 和林格尔县| 景德镇市| 崇州市| 冷水江市| 虹口区| 平阳县| 砀山县| 城步| 沽源县| 武威市| 昆明市| 西峡县| 德江县| 调兵山市| 易门县| 正镶白旗| 麦盖提县| 九江市| 新乐市|