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

Java類的加載時(shí)機(jī)

 更新時(shí)間:2021年12月12日 16:38:18   作者:江南入直  
這篇文章介紹了Java類的加載時(shí)機(jī),文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

必須初始化的四種情況

有四種情況類是必須要進(jìn)行初始化的,對(duì)于這四種情況原文描述如下:

但是對(duì)于初始化階段,虛擬機(jī)規(guī)范則是嚴(yán)格規(guī)定了有且只有4種情況必須立即對(duì)類進(jìn)行初始化,而加載、驗(yàn)證、準(zhǔn)備自然需要在此之前開始。

  • 1:遇到new、getstatic、putstatic或invokestatic這4條字節(jié)碼指令時(shí),如果類沒(méi)有進(jìn)行過(guò)初始化,則需要先觸發(fā)其初始化。生成這4條指令最常見的java代碼場(chǎng)景是:使用new關(guān)鍵字實(shí)例化對(duì)象的時(shí)候、讀取或設(shè)置一個(gè)類的靜態(tài)字段(被final修飾、已在編譯期把結(jié)果放入常量池的靜態(tài)字段除外)的時(shí)候,以及調(diào)用一個(gè)類的靜態(tài)方法的時(shí)候。
  • 2:使用java.lang.reflect包的方法對(duì)類進(jìn)行反射調(diào)用的時(shí)候,如果類沒(méi)有進(jìn)行過(guò)初始化,則需要先觸發(fā)其初始化。
  • 3:當(dāng)初始化一個(gè)類的時(shí)候,如果發(fā)現(xiàn)其父類還沒(méi)有進(jìn)行過(guò)初始化,則需要先觸發(fā)其父類的初始化。
  • 4:當(dāng)虛擬機(jī)啟動(dòng)時(shí),用戶需要指定一個(gè)要執(zhí)行的主類(包含main()方法的那個(gè)類),虛擬機(jī)會(huì)先初始化這個(gè)主類。

以上四點(diǎn)我們一一用代碼來(lái)驗(yàn)證,第一點(diǎn)里面說(shuō)到了四種初始化的場(chǎng)景,分別是:

  • ①用new關(guān)鍵字實(shí)例化對(duì)象
  • ②讀取類靜態(tài)字段
  • ③設(shè)置類的靜態(tài)字段
  • ④調(diào)用一個(gè)類的靜態(tài)方法

在驗(yàn)證之前需要達(dá)成一個(gè)共識(shí):虛擬機(jī)在初始化類時(shí)會(huì)執(zhí)行static語(yǔ)句塊中的操作,因此我們可以根據(jù)靜態(tài)語(yǔ)句塊中的代碼是否執(zhí)行了來(lái)判斷類是否加載。為此我創(chuàng)建了一個(gè)SubClass類

package com.test.jvm.classloading;

/**
 * @author fc
 */
public class SubClass {
    static{
        System.out.println("子類初始化");
    }
    public static int a = 10;

    public static int getA(){
        return a;
    }
}

在main方法中分別執(zhí)行(每次執(zhí)行一條)以下四條代碼來(lái)模擬上面四個(gè)場(chǎng)景

package com.test.jvm.classloading;

/**
 * @author fc
 */
public class Main {
    public static void main(String[] args) {
        SubClass subClass = new SubClass();
        System.out.println(SubClass.a);
        SubClass.getA();
        SubClass.a = 30;
    }
}

結(jié)果不出所料,輸出結(jié)果都包含"子類初始化",說(shuō)明以上四種方式確實(shí)可以會(huì)觸發(fā)類的初始化。

接下來(lái)看第二點(diǎn),對(duì)類進(jìn)行反射調(diào)用時(shí)會(huì)觸發(fā)類的初始化

package com.test.jvm.classloading;

/**
 * @author fc
 */
public class Main {
    public static void main(String[] args) throws ClassNotFoundException {
        Class.forName("com.test.jvm.classloading.SubClass");
    }
}

以上的反射調(diào)用同樣正常輸出了"子類初始化"。

第三點(diǎn)如果父類沒(méi)有進(jìn)行初始化,則要先觸發(fā)父類的初始化,再創(chuàng)建一個(gè)父類,并且讓之前的子類繼承父類

package com.test.jvm.classloading;

/**
 * @author fc
 */
public class SuperClass {
    static {
        System.out.println("父類初始化");
    }
    public static int b = 20;
}
package com.test.jvm.classloading;

/**
 * @author fc
 */
public class SubClass extends SuperClass {
    static{
        System.out.println("子類初始化");
    }
    public static int a = 10;

    public static int getA(){
        return a;
    }
}

這時(shí)我們?cè)俅螆?zhí)行上面的main方法里面的任意一條測(cè)試語(yǔ)句,這時(shí)發(fā)現(xiàn)在原來(lái)的輸出"子類初始化"前輸出了"父類初始化",說(shuō)明了兩點(diǎn):①父類同樣會(huì)初始化;②父類會(huì)先于子類初始化。

第四點(diǎn)虛擬機(jī)會(huì)先初始化包含main方法的主類,這時(shí)我們?cè)谥黝愔屑尤腱o態(tài)代碼塊

package com.test.jvm.classloading;

/**
 * @author fc
 */
public class Main {
    static {
        System.out.println("初始化主類");
    }
    public static void main(String[] args) throws ClassNotFoundException {
        SubClass subClass = new SubClass();
    }
}

可以看到輸出結(jié)果如下,完全印證了第四點(diǎn)。

不主動(dòng)進(jìn)行初始化

而對(duì)于不會(huì)主動(dòng)進(jìn)行初始化的情況在該書中也有以下幾種情況

第一種是通過(guò)子類類名調(diào)用父類靜態(tài)代碼(包括靜態(tài)方法和靜態(tài)變量)不會(huì)進(jìn)行初始化,以下也通過(guò)代碼進(jìn)行說(shuō)明

package com.test.jvm.classloading;

/**
 * @author fc
 */
public class Main {
    public static void main(String[] args) throws ClassNotFoundException {
        System.out.println(SubClass.b);
    }
}

輸出如下,可以看到只初始化了父類而沒(méi)有初始化子類。

第二種是通過(guò)數(shù)組來(lái)創(chuàng)建對(duì)象不會(huì)觸發(fā)此類的初始化

package com.test.jvm.classloading;

/**
 * @author fc
 */
public class Main {
    public static void main(String[] args) throws ClassNotFoundException {
        SuperClass[] supers = new SuperClass[10];
    }
}

輸出為空。

第三種是調(diào)用final修飾的常量不會(huì)觸發(fā)類的初始化,為此我在父類中加了一個(gè)常量

package com.test.jvm.classloading;

/**
 * @author fc
 */
public class SuperClass {
    static {
        System.out.println("父類初始化");
    }
    public static int b = 20;

    public final static String STATE = "常量";
}
package com.test.jvm.classloading;

/**
 * @author fc
 */
public class Main {
    public static void main(String[] args) {
        System.out.println(SuperClass.STATE);
    }
}

可以看到輸出結(jié)果只是打印了常量的值,并沒(méi)有初始化這個(gè)類。

補(bǔ)充

到這里對(duì)于書中描述的類的加載時(shí)機(jī)都已經(jīng)用例子說(shuō)明了,接下來(lái)展示一個(gè)在博主Boblim那看到的一個(gè)例子

/**
 * @author fc
 */
class SingleTon {
    private static SingleTon singleTon = new SingleTon();
    public static int count1;
    public static int count2 = 0;

    private SingleTon() {
        count1++;
        count2++;
    }

    public static SingleTon getInstance() {
        return singleTon;
    }
}

public class Test {
    public static void main(String[] args) {
        SingleTon.getInstance();
        System.out.println("count1=" + SingleTon.count1);
        System.out.println("count2=" + SingleTon.count2);
    }
}

輸出count1=1,count2=0,關(guān)于為什么會(huì)輸出這個(gè)結(jié)果在那篇鏈接的博客已經(jīng)做了詳細(xì)的說(shuō)明,同時(shí)這個(gè)輸出結(jié)果也很好地佐證了下面這句話

類構(gòu)造器<clinit>()方法是由編譯器自動(dòng)收集類中的所有類變量的賦值動(dòng)作和靜態(tài)語(yǔ)句塊(static塊)中的語(yǔ)句合并產(chǎn)生的,編譯器收集的順序是由語(yǔ)句在源文件中出現(xiàn)的順序所決定的。

正是給類變量賦值時(shí)是按照順序進(jìn)行的,所以上面count2又會(huì)被重新賦值為0,才導(dǎo)致這個(gè)輸出結(jié)果。

以上所述是小編給大家介紹的Java類的加載時(shí)機(jī),希望對(duì)大家有所幫助。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!

相關(guān)文章

  • Java泛型機(jī)制必要性及原理解析

    Java泛型機(jī)制必要性及原理解析

    這篇文章主要介紹了Java泛型機(jī)制必要性及原理解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-05-05
  • 深入理解Java 對(duì)象和類

    深入理解Java 對(duì)象和類

    下面小編就為大家?guī)?lái)一篇深入理解Java 對(duì)象和類。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-05-05
  • Java通俗易懂系列設(shè)計(jì)模式之模板模式

    Java通俗易懂系列設(shè)計(jì)模式之模板模式

    這篇文章主要介紹了Java通俗易懂系列設(shè)計(jì)模式之模板模式,想了解設(shè)計(jì)模式的同學(xué),可以仔細(xì)看一下
    2021-04-04
  • 繼承jpa?Repository?寫自定義方法查詢實(shí)例

    繼承jpa?Repository?寫自定義方法查詢實(shí)例

    這篇文章主要介紹了繼承jpa?Repository?寫自定義方法查詢實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • jmeter正則表達(dá)式實(shí)例詳解

    jmeter正則表達(dá)式實(shí)例詳解

    正則表達(dá)式就是記錄文本規(guī)則的代碼。學(xué)習(xí)正則表達(dá)式最好就是從實(shí)例下手。下面我們通過(guò)實(shí)例代碼給大家介紹jmeter正則表達(dá)式的相關(guān)知識(shí),感興趣的朋友一起看看吧
    2021-12-12
  • Java批量寫入文件和下載圖片的示例代碼

    Java批量寫入文件和下載圖片的示例代碼

    這篇文章主要介紹了Java批量寫入文件和下載圖片的示例代碼,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下
    2020-09-09
  • 基于Spring實(shí)現(xiàn)文件上傳功能

    基于Spring實(shí)現(xiàn)文件上傳功能

    這篇文章主要為大家詳細(xì)介紹了Spring實(shí)現(xiàn)文件上傳功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-09-09
  • Jsoup解析html實(shí)現(xiàn)招聘信息查詢功能

    Jsoup解析html實(shí)現(xiàn)招聘信息查詢功能

    這篇文章主要為大家詳細(xì)介紹了Jsoup解析html實(shí)現(xiàn)招聘信息查詢功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • 詳解SpringBoot自定義配置與整合Druid

    詳解SpringBoot自定義配置與整合Druid

    Druid是alibaba開源平臺(tái)上一個(gè)數(shù)據(jù)庫(kù)連接池實(shí)現(xiàn),結(jié)合了C3P0,DBCP等DB池的優(yōu)點(diǎn),同時(shí)也有Web監(jiān)控界面。這篇文章主要介紹了Java之SpringBoot自定義配置與整合Druid的相關(guān)知識(shí),需要的朋友可以參考下
    2021-09-09
  • Java并發(fā)容器ConcurrentLinkedQueue解析

    Java并發(fā)容器ConcurrentLinkedQueue解析

    這篇文章主要介紹了Java并發(fā)容器ConcurrentLinkedQueue解析,
    2023-12-12

最新評(píng)論

堆龙德庆县| 洛扎县| 秭归县| 营口市| 游戏| 通城县| 恭城| 绥棱县| 陵水| 同江市| 湘阴县| 秦安县| 宁都县| 奇台县| 姚安县| 鄄城县| 江源县| 四平市| 大庆市| 长岭县| 岳阳市| 绍兴市| 垣曲县| 金昌市| 保山市| 阳原县| 通河县| 连平县| 红桥区| 西安市| 堆龙德庆县| 富顺县| 邵阳县| 东乌| 霍邱县| 山东| 隆尧县| 永和县| 津市市| 通河县| 晋城|