亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

分析Java中的類加載問(wèn)題

 更新時(shí)間:2021年06月25日 08:46:41   作者:華為云開(kāi)發(fā)者社區(qū)  
很多時(shí)候提到類加載,大家總是沒(méi)法馬上回憶起順序,這篇文章會(huì)用一個(gè)例子為你把類加載的諸多問(wèn)題一次性澄清

一、Java類的加載順序

引用1個(gè)網(wǎng)上的經(jīng)典例子,并做稍許改動(dòng),以便大家更好地理解。

public class Animal {
    private int i = test();
    private static int j  = method();
    static {
        System.out.println("a");
    }
    Animal(){
        System.out.println("b");
    }
    {
        System.out.println("c");
    }
    public int test(){
        System.out.println("d");
        return 1;
    }
    public static int method(){
        System.out.println("e");
        return 1;
    }
}
public class Dog extends Animal{
    {
        System.out.println("h");
    }
    private int i = test();
    static {
        System.out.println("f");
    }
    private static int j  = method();

    Dog(){
        System.out.println("g");
    }
    public int test(){
        System.out.println("i");
        return 1;
    }
    public static int method(){
        System.out.println("j");
        return 1;
    }
    public static void main(String[] args) {
        Dog dog = new Dog();
        System.out.println();
        Dog dog1 = new Dog();
    }
}

執(zhí)行這段main程序,會(huì)輸出什么?

答案是

eafjicbhig
icbhig

為了方便大家一個(gè)個(gè)細(xì)節(jié)去理解, 我換一種方式去提問(wèn)。

Q: 什么時(shí)候會(huì)進(jìn)行靜態(tài)變量的賦值和靜態(tài)代碼塊的執(zhí)行?

A:

  • 第一次創(chuàng)建某個(gè)類或者某個(gè)類的子類的實(shí)例
  • 訪問(wèn)類的靜態(tài)變量、調(diào)用類的靜態(tài)方法
  • 使用反射方法forName
  • 調(diào)用主類的main方法(本例子的第一次靜態(tài)初始化其實(shí)屬于這個(gè)情況,調(diào)用了Dog的main方法)

注: 類初始化只會(huì)進(jìn)行一次, 上面任何一種情況觸發(fā)后,之后都不會(huì)再引起類初始化操作。

Q:初始化某個(gè)子類時(shí),也會(huì)對(duì)父類做靜態(tài)初始化嗎?順序呢?

A:如果父類之前沒(méi)有被靜態(tài)初始化過(guò),那就會(huì)進(jìn)行, 且順序是先父類再子類。 后面的非靜態(tài)成員初始化也是如此。
所以會(huì)先輸出eafj。

Q: 為什么父類的method不會(huì)被子類的method重寫(xiě)?

A: 靜態(tài)方法是類方法,不會(huì)被子類重寫(xiě)。畢竟類方法調(diào)用時(shí),是必定帶上類名的。

Q: 為什么第一個(gè)輸出的是e而不是a?

A: 因?yàn)轭愖兞康娘@示賦值代碼和靜態(tài)代碼塊代碼按照從上到下的順序執(zhí)行。

Animal的靜態(tài)初始化過(guò)程中,method的調(diào)用在static代碼塊之前,所以先輸出e再輸出a。

而Dog的靜態(tài)初始化過(guò)程中,method的調(diào)用在static代碼塊之后,因此先輸出f,再輸出j

Q: 沒(méi)有在子類的構(gòu)造器中調(diào)用super()時(shí),也會(huì)進(jìn)行父類對(duì)象的實(shí)例化嗎?

A: 會(huì)的。會(huì)自動(dòng)調(diào)用父類的默認(rèn)構(gòu)造器。 super()主要是用于需要調(diào)用父類的特殊構(gòu)造器的情況。
因此會(huì)先進(jìn)行Animal的對(duì)象實(shí)例化,再進(jìn)行Dog的對(duì)象實(shí)例化

Q: 構(gòu)造方法、成員顯示賦值、非靜態(tài)代碼塊(即輸出c和h的那2句)的順序是什么?

A:

1.成員顯示賦值、非靜態(tài)代碼塊(按定義順序)

2.構(gòu)造方法

因此Animal的實(shí)例化過(guò)程輸出icb(如果對(duì)輸出i有疑問(wèn),見(jiàn)下面一題)
接著進(jìn)行Dog的實(shí)例化,輸出hig

Q: 為什么Animal實(shí)例化時(shí), i=test()中輸出的是i而不是d?

A:因?yàn)槟阏嬲齽?chuàng)建的是Dog子類,Dog子類中的test()方法由于簽名和父類test方法一致,因此test方法被重寫(xiě)了。
此時(shí)即使在父類中調(diào)用,也還是用使用子類Dog的方法。除非你new的是Animal。

Q: 同上題, 如果test方法都是private或者final屬性, 那么上題的情況會(huì)有變化嗎??

A:

因?yàn)閜rivate和final方法是不能被子類重寫(xiě)的。
所以Animal實(shí)例化時(shí),i=test輸出d。

總結(jié)一下順序:

1.父類靜態(tài)變量顯式賦值、父類靜態(tài)代碼塊(按定義順序)

2.子類靜態(tài)變量顯式賦值、子類靜態(tài)代碼塊(按定義順序)

3.父類非靜態(tài)變量顯式賦值(父類實(shí)例成員變量)、父類非靜態(tài)代碼塊(按定義順序)

4.父類構(gòu)造函數(shù)

5.子類非靜態(tài)變量(子類實(shí)例成員變量)、子類非靜態(tài)代碼塊(按定義順序)

6.子類構(gòu)造函數(shù)。

二、類加載過(guò)程

Q:類加載的3個(gè)必經(jīng)階段是:

A:

1.加載(類加載器讀取二進(jìn)制字節(jié)流,生成java類對(duì)象)

2.鏈接(驗(yàn)證,分配靜態(tài)域初始零值)

3.初始化(前面的題目講的其實(shí)就是初始化時(shí)的順序)

更詳細(xì)的如下:

三、被動(dòng)引用中和類靜態(tài)初始化的關(guān)系

Q:new某個(gè)類的數(shù)組時(shí),會(huì)引發(fā)類初始化嗎?

像下面輸出什么

public class Test {
    static class A{
        public static int a = 1;
        static{
            System.out.println("initA");
        }
    }
 
    public static void main(String[] args) {
        A[] as = new A[5];
    }
}

A:

new數(shù)組時(shí),不會(huì)引發(fā)類初始化。
什么都不輸出。

Q:引用類的final靜態(tài)字段,會(huì)引發(fā)類初始化嗎?

像下面輸出什么?

public class Test {
    static class A{
        public static final int a = 1;
        static{
            System.out.println("initA");
        }
    }

    public static void main(String[] args) {
        System.out.println("A.a=" + A.a);
    }
}

A: 不會(huì)引發(fā)。

不會(huì)輸出initA。 去掉final就會(huì)引發(fā)了。
(注意這里必須是基本類型常量, 如果是引用類型產(chǎn)量,則會(huì)引發(fā)類初始化)

Q:子類引用了父類的靜態(tài)成員,此時(shí)子類會(huì)做類初始化嘛?

如下會(huì)輸出什么

public class Test {
    static class A{
        public static int a = 1;
        static{
            System.out.println("initA");
        }
    }

    static class B extends A{
        static {
            System.out.println("initB");
        }
    }

    public static void main(String[] args) {
        System.out.println("B.a=" + B.a);
    }
}

A:

子類不會(huì)初始化。
打印initA,卻不會(huì)打印initB。

四、類加載器雙親委派

類加載時(shí)的雙親委派模型,不知道能怎么出題。。。反正就記得優(yōu)先去父類加載器中看類是否能加載。

Bootsrap不是ClassLoader的子類,他是C++編寫(xiě)的。
而ExtClassLoader和AppClassLoader都是繼承自ClassLoader的

Q:java中, 是否類和接口的包名和名字相同, 那么就一定是同一個(gè)類或者接口?

A:錯(cuò)誤。

1個(gè)jvm中, 類和接口的唯一性由二進(jìn)制名稱以及它的定義類加載器共同決定。
因此2個(gè)不同的加載器加載出來(lái)相同的類或接口時(shí), 實(shí)際上是不同的。

以上就是分析Java中的類加載問(wèn)題的詳細(xì)內(nèi)容,更多關(guān)于Java 類加載的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java IO之包裝流詳解

    Java IO之包裝流詳解

    這篇文章主要為大家介紹了Java IO之包裝流,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-01-01
  • Java聊天室之使用Socket實(shí)現(xiàn)通信功能

    Java聊天室之使用Socket實(shí)現(xiàn)通信功能

    這篇文章主要為大家詳細(xì)介紹了Java簡(jiǎn)易聊天室之使用Socket實(shí)現(xiàn)通信功能,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,需要的可以了解一下
    2022-10-10
  • spring boot task實(shí)現(xiàn)動(dòng)態(tài)創(chuàng)建定時(shí)任務(wù)的方法

    spring boot task實(shí)現(xiàn)動(dòng)態(tài)創(chuàng)建定時(shí)任務(wù)的方法

    這篇文章主要介紹了spring boot task實(shí)現(xiàn)動(dòng)態(tài)創(chuàng)建定時(shí)任務(wù),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-01-01
  • 基于java變量和作用域以及成員變量的默認(rèn)初始化(詳解)

    基于java變量和作用域以及成員變量的默認(rèn)初始化(詳解)

    下面小編就為大家介紹一下java變量和作用域以及成員變量的默認(rèn)初始化,具有很好的參考價(jià)值,希望對(duì)大家有所幫助
    2017-11-11
  • springboot打成jar后無(wú)法讀取根路徑和文件的解決

    springboot打成jar后無(wú)法讀取根路徑和文件的解決

    這篇文章主要介紹了springboot打成jar后無(wú)法讀取根路徑和文件的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • IDEA如何實(shí)現(xiàn)顯示類的所有方法

    IDEA如何實(shí)現(xiàn)顯示類的所有方法

    這篇文章主要介紹了IDEA如何顯示類的所有方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • java實(shí)現(xiàn)去除ArrayList重復(fù)字符串

    java實(shí)現(xiàn)去除ArrayList重復(fù)字符串

    本文主要介紹了java實(shí)現(xiàn)去除ArrayList重復(fù)字符串,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-09-09
  • Java中的Spring Security配置過(guò)濾器

    Java中的Spring Security配置過(guò)濾器

    這篇文章主要介紹了Java中的Spring Security配置過(guò)濾器,文章通過(guò)圍繞文章主題的相關(guān)資料展開(kāi)詳細(xì)內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-05-05
  • 在eclipse中使用SVN的實(shí)現(xiàn)方法(圖文教程)

    在eclipse中使用SVN的實(shí)現(xiàn)方法(圖文教程)

    這篇文章主要介紹了在eclipse中使用SVN的實(shí)現(xiàn)方法(圖文教程),文中通過(guò)圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • springboot ApplicationContextInitializer的三種使用方法小結(jié)

    springboot ApplicationContextInitializer的三種使用方法小結(jié)

    這篇文章主要介紹了關(guān)于ApplicationContextInitializer的三種使用方法小結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11

最新評(píng)論