欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java類的加載時機

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

必須初始化的四種情況

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

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

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

以上四點我們一一用代碼來驗證,第一點里面說到了四種初始化的場景,分別是:

  • ①用new關鍵字實例化對象
  • ②讀取類靜態(tài)字段
  • ③設置類的靜態(tài)字段
  • ④調用一個類的靜態(tài)方法

在驗證之前需要達成一個共識:虛擬機在初始化類時會執(zhí)行static語句塊中的操作,因此我們可以根據(jù)靜態(tài)語句塊中的代碼是否執(zhí)行了來判斷類是否加載。為此我創(chuàng)建了一個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í)行一條)以下四條代碼來模擬上面四個場景

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;
    }
}

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

接下來看第二點,對類進行反射調用時會觸發(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");
    }
}

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

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

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;
    }
}

這時我們再次執(zhí)行上面的main方法里面的任意一條測試語句,這時發(fā)現(xiàn)在原來的輸出"子類初始化"前輸出了"父類初始化",說明了兩點:①父類同樣會初始化;②父類會先于子類初始化。

第四點虛擬機會先初始化包含main方法的主類,這時我們在主類中加入靜態(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();
    }
}

可以看到輸出結果如下,完全印證了第四點。

不主動進行初始化

而對于不會主動進行初始化的情況在該書中也有以下幾種情況

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

package com.test.jvm.classloading;

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

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

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

package com.test.jvm.classloading;

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

輸出為空。

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

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);
    }
}

可以看到輸出結果只是打印了常量的值,并沒有初始化這個類。

補充

到這里對于書中描述的類的加載時機都已經(jīng)用例子說明了,接下來展示一個在博主Boblim那看到的一個例子

/**
 * @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,關于為什么會輸出這個結果在那篇鏈接的博客已經(jīng)做了詳細的說明,同時這個輸出結果也很好地佐證了下面這句話

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

正是給類變量賦值時是按照順序進行的,所以上面count2又會被重新賦值為0,才導致這個輸出結果。

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

相關文章

  • Java Integer.ValueOf()的一些了解

    Java Integer.ValueOf()的一些了解

    這篇文章主要介紹了Java Integer.ValueOf()的一些了解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-05-05
  • Java實現(xiàn)插入排序,希爾排序和歸并排序

    Java實現(xiàn)插入排序,希爾排序和歸并排序

    這篇文章主要為大家詳細介紹了插入排序,希爾排序和歸并排序的多種語言的實現(xiàn)(JavaScript、Python、Go語言、Java),感興趣的小伙伴可以了解一下
    2022-12-12
  • 在Spring Boot中如何使用Cookies詳析

    在Spring Boot中如何使用Cookies詳析

    這篇文章主要給大家介紹了關于在Spring Boot中如何使用Cookies的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者使用Spring Boot具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-11-11
  • Java?HashMap中除了死循環(huán)之外的那些問題

    Java?HashMap中除了死循環(huán)之外的那些問題

    這篇文章主要介紹了Java?HashMap中除了死循環(huán)之外的那些問題,這些問題大致可以分為兩類,程序問題和業(yè)務問題,下面文章我們一個一個來看,需要的小伙伴可以參考一下
    2022-05-05
  • Java8新特性lambda表達式有什么用(用法實例)

    Java8新特性lambda表達式有什么用(用法實例)

    這篇文章主要介紹了Java8新特性lambda表達式有什么用,著重以實例講解lambda表達式,需要的朋友可以參考下
    2014-06-06
  • Java日常練習題,每天進步一點點(64)

    Java日常練習題,每天進步一點點(64)

    下面小編就為大家?guī)硪黄狫ava基礎的幾道練習題(分享)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧,希望可以幫到你
    2021-09-09
  • 關于Java中@SuppressWarnings的正確使用方法

    關于Java中@SuppressWarnings的正確使用方法

    這篇文章主要介紹了關于Java中@SuppressWarnings的正確使用方法,@SuppressWarnings注解主要用在取消一些編譯器產生的警告對代碼左側行列的遮擋,有時候這會擋住我們斷點調試時打的斷點,需要的朋友可以參考下
    2023-05-05
  • 詳解Java編程中對線程的中斷處理

    詳解Java編程中對線程的中斷處理

    這篇文章主要介紹了Java編程中對線程的中斷處理,特別講解了中斷的時機與中斷狀態(tài)的管理,需要的朋友可以參考下
    2015-11-11
  • mybatis中foreach嵌套if標簽方式

    mybatis中foreach嵌套if標簽方式

    這篇文章主要介紹了mybatis中foreach嵌套if標簽方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • 排序算法圖解之Java快速排序的分步刨析

    排序算法圖解之Java快速排序的分步刨析

    快速排序是通過一趟排序將要排序的數(shù)據(jù)分割為獨立的兩個部分,一部分的所有數(shù)據(jù)比另外一部分的所有數(shù)據(jù)要小,然后按照此方法對這兩部分分別進行快速排序,整個過程可以遞歸進行,以此達到整個數(shù)據(jù)變成有序序列。本文通過示例講解了快速排序的實現(xiàn),需要的可以參考一下
    2022-11-11

最新評論