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

一文搞懂java中類及static關鍵字執(zhí)行順序

 更新時間:2022年09月01日 16:17:56   作者:nianyuw  
這篇文章主要介紹了一文搞懂java中類及static關鍵字執(zhí)行順序,文章通過類的生命周期展開詳細的內容介紹,具有一定的參考價值,需要的小伙伴可以參考一下

類的生命周期

  • 加載:classpath、jar包、網絡、某個磁盤位置下的類的class二進制字節(jié)流讀進來,在內存中生成一個代表這個類的java.lang.Class對象放入元空間(方法區(qū),永久代),此階段我們程序員可以干預,我們可以自定義類加載器來實現類的加載;
  • 驗證:驗證Class文件的字節(jié)流中包含的信息符合《Java虛擬機規(guī)范》的全部約束要求,保證虛擬機的安全;
  • 準備:類變量賦默認初始值,int為0,long為0L,boolean為false,引用類型為null;常量賦正式值;
  • 解析:把符號引用翻譯為直接引用;
  • 初始化:當我們new一個類的對象,訪問一個類的靜態(tài)屬性,修改一個類的靜態(tài)屬性,調用一個類的靜態(tài)方法,用反射API對一個類進行調用,初始化當前類,其父類也會被初始化… 那么這些都會觸發(fā)類的初始化;

靜態(tài)變量的初始化有兩種途徑: (1)在靜態(tài)變量的聲明處進行初始化 (2)在靜態(tài)代碼塊中進行初始化

使用:使用這個類;卸載:

  • 1.該類所有的實例都已經被GC,也就是JVM中不存在該Class的任何實例;
  • 2.加載該類的ClassLoader已經被GC;
  • 3.該類的java.lang.Class 對象沒有在任何地方被引用,如不能在任何地方通過反射訪問該類的方法;

接著我們來了解static關鍵字的作用和使用條件

static關鍵字

static關鍵字修飾的數據存儲在我們的方法區(qū)中的靜態(tài)常量池中,static可以修飾方法、變量和代碼塊

static修飾方法:指定不需要實例化就可以激活的一個方法。this關鍵字不能再static方法中使用靜態(tài)方法中不能使用非靜態(tài)方法非靜態(tài)方法可以調用靜態(tài)方法。

static修飾變量:指定變量被所有對象共享,即所有實例都可以使用該變量。變量屬于這個類。

static修飾代碼塊:無論放在哪里,都是放在main方法運行的。通常用于初始化靜態(tài)變量,靜態(tài)代碼塊屬于類。不可以省略,沒加static認為是構造代碼塊

static關鍵字執(zhí)行順序

先記住幾個準則;

  • 實例化對象前,先加載類(對象載入之前,一定要是類先被載入)
  • 類(或者靜態(tài)變量和靜態(tài)代碼塊)在生命周期結束前,只執(zhí)行一次
  • 靜態(tài)變量(屬性)和靜態(tài)代碼塊誰先聲明誰先執(zhí)行非
  • 靜態(tài)變量(屬性)和非靜態(tài)代碼塊誰先聲明誰先執(zhí)行靜態(tài)
  • 構造代碼塊是和類同時加載的,構造代碼塊是在實例化之后執(zhí)行構造方法之前執(zhí)行的構造方法是在構造代碼塊執(zhí)行完之后才執(zhí)行的。
  • 靜態(tài)方法屬于類的,加載完類就可以調用靜態(tài)方法(可以執(zhí)行多次);非靜態(tài)方法是屬于對象的,加載完對象就可以調用非靜態(tài)方法。
  • 每創(chuàng)建一個對象,即每載入一個對象,非靜態(tài)代碼塊都執(zhí)行一次。執(zhí)行類對象的載入之前就會調用

我們來通過一個例子來驗證以下上面的觀點

InitializeDemo.java

package com.qcby.demo.staticDemo;

/**
 * @ClassName TRRest
 * @Description TODO
 * @Author heaboy@heaboy.com
 * @Version 1.0.0
 */
public class InitializeDemo {
    private static int k = 1;
    private static InitializeDemo t1 = new InitializeDemo("t1");
    private static InitializeDemo t2 = new InitializeDemo("t2");
    private static int i = print("i");
    private static int n = 99;

    {
        print("初始化塊");
        j=100;
    }
    public InitializeDemo(String str) {
        System.out.println((k++) + ":" + str + "   i=" + i + "    n=" + n);
        ++i;
        ++n;

    }
    static {
        print("靜態(tài)塊");
        n=100;
    }
    private int j = print("j");
    public static int print(String str) {
        System.out.println((k++) + ":" + str + "   i=" + i + "    n=" + n);
        ++n;
        return ++i;
    }
    public static void main(String[] args) {
        InitializeDemo test = new InitializeDemo("test");
    }
}

輸出結果:

我們來逐個分析,

一開始調用main方法,main方法內實例化InitializeDemo的對象,在對象載入之前,一定要是類先被載入

所以我們先加載InitializeDemo類,加載類的同時,會加載靜態(tài)變量和靜態(tài)代碼塊,但是是按順序執(zhí)行,且只執(zhí)行一次

先加載如下靜態(tài)變量

private static int k = 1;

加載如下靜態(tài)變量的時候,發(fā)現要去加載類,由于類以及加載了,所以會加載這個對象,這個對象加載前,會執(zhí)行非靜態(tài)代碼塊

private static InitializeDemo t1 = new InitializeDemo("t1");

此時也就是

1:初始化塊 i=0 n=0

接著執(zhí)行

private int j = print("j");

2:j i=1 n=1

接著執(zhí)行構造方法,

public InitializeDemo(String str) {
        System.out.println((k++) + ":" + str + "   i=" + i + "    n=" + n);
        ++i;
        ++n;

    }

3:t1 i=2 n=2

t1的實例化執(zhí)行結束,接著執(zhí)行t2的實例化

private static InitializeDemo t2 = new InitializeDemo("t2");

結果和上述一致,按非靜態(tài)代碼塊和非靜態(tài)屬性然后構造方法方法的順序執(zhí)行

4:初始化塊 i=3 n=3

5:j i=4 n=4

6:t2 i=5 n=5

兩個靜態(tài)屬性(實例化)執(zhí)行完,執(zhí)行如下代碼

private static int i = print("i");

7:i i=6 n=6

接著執(zhí)行下面的代碼,此時n變成了99

private static int n = 99;

接著執(zhí)行靜態(tài)代碼塊

static {
        print("靜態(tài)塊");
        n=100;
    }

8:靜態(tài)塊 i=7 n=99

類加載完畢,執(zhí)行test對象的載入,參考t1,t2的實例化,按非靜態(tài)代碼塊和非靜態(tài)屬性然后構造方法方法的順序執(zhí)行

9:初始化塊 i=8 n=100

10:j i=9 n=101

11:test i=10 n=102

繼承中的static執(zhí)行順序

例子一:

package com.qcby.demo.oop;

public class Test3 extends Base {
    static {
        System.out.println("test static");
    }
    public Test3(){
        System.out.println("test constructor");
    }

    public static void main(String[] args) {
        new Test3();
    }
}
class Base{
    static {
        System.out.println("Base static");
    }
    public Base(){
        System.out.println("Base constructor");
    }
}

執(zhí)行Test3的構造方法,要先加載Test3的類加載,由于Test3繼承于Base,所以他要先加載父類Base,

所以先Base static 后test static 在執(zhí)行子類的構造方法的時候,要先執(zhí)行父類的構造方法,如果是多級繼承,會先執(zhí)行最頂級父類的構造方法,然后依次執(zhí)行各級個子類的構造方法。 所以先執(zhí)行Base constructor后執(zhí)行test constructor結果就如上圖

例子二(重點)

package com.qcby.demo.oop;

public class MyTest {
    MyPerson person = new MyPerson("test");//這里可以理解為成員變量輔助,,要先把MyPerson先加載到jvm中
    static {
        System.out.println("test static");//1
    }

    public MyTest() {
        System.out.println("test constructor");//5
    }

    public static void main(String[] args) {//main方法在MyTest類中,使用mian方法先加載MyTest的靜態(tài)方法,不調用其他,
        MyClass myClass =new MyClass();//對象創(chuàng)建的時候,會加載對應的成員變量
    }
}
class MyPerson {
    static {
        System.out.println("person static");//3
    }

    public MyPerson(String str) {
        System.out.println("person " + str);//4  6
    }
}
class MyClass extends MyTest {
    MyPerson person = new MyPerson("class");//這里可以理解為成員變量輔助,要先把MyPerson先加載到jvm中
    static {
        System.out.println("class static");//2
    }
    
    public MyClass() {
        //默認super()
        System.out.println("class constructor");//7
    }
}

1.先看main方法,main方法回先加載對應的類,此時MyTest類和其靜態(tài)的變量,方法和代碼塊會隨類的加載而開辟空間。static是屬于類的。所以test static優(yōu)先執(zhí)行,且此時MyTest類的其他語句不執(zhí)行。

2.mian方法中調用了MyClass myClass =new MyClass(),實例化了一個MyClass類的對象,這時候會初始化對象的成員變量和調用對象的構造函數,而MyClass類繼承于MyTest類,在加載MyClass類前,會先調用MyTest類,但是MyTest類以及其靜態(tài)的變量,方法和代碼塊已經加載(在類的生命周期只執(zhí)行一次),所以返回到子類(MyClass類)的加載,這時候會調用MyClass類的靜態(tài)的變量,方法和代碼塊。所以class static第二個執(zhí)行。

3.MyClass類加載完后,應該接著調用MyClass類的構造方法,在調用子類的構造方法前,會默認調用父類的無參構造方法(super()省略),調用父類的無參構造方法,相當于實例化父類的對象,這時候會先初始化對象的成員變量,這里的MyPerson person = new MyPerson(“test”);就相當于成員變量(屬于對象,在對象的實例化的時候才加載),于是會加載MyPerson類和其靜態(tài)的變量,方法和代碼塊。所以person static第三個執(zhí)行

4.加載完MyPerson類和其靜態(tài)的變量,方法和代碼塊后,會調用MyPerson類和的有參構造方法,即person test第四個執(zhí)行

5.MyPerson類和的有參構造方法執(zhí)行結束,返回父類MyTest,父類調用構造方法,即test constructor第五個執(zhí)行

6.父類MyTest構造方法執(zhí)行結束,返回子類,子類再調用構造方法前,先初始化對象的成員變量MyPerson person = new MyPerson(“class”);,這時候會先先加載MyPerson 和其靜態(tài)的變量,方法和代碼塊。由于上述類以及加載,所以直接執(zhí)行其有參構造方法,即person class第六個執(zhí)行

7.MyPerson類和的有參構造方法執(zhí)行結束,返回子類MyClass,子類調用構造方法,即class constructor第七個執(zhí)行

父類static代碼塊–>子類static代碼塊–>父類普通代碼塊(成員對象屬性初始化)–>父類構造方法–>子類普通代碼塊(成員對象屬性初始化–>子類構造方法

總結

類加載順序的三個原則是

  • 1、父類優(yōu)先于子類
  • 2、屬性和代碼塊(看先后順序)優(yōu)先于構造方法
  • 3、靜態(tài)優(yōu)先于非靜態(tài)

類加載順序為(默認變量卸載代碼塊前)

父類靜態(tài)變量->父類靜態(tài)語句塊->子類靜態(tài)變量->子類靜態(tài)語句塊->父類普通成員變量->父類動態(tài)語句塊->父類構造器->子類普通成員變量->子類動態(tài)語句塊->子類構造器

到此這篇關于一文搞懂java中類及static關鍵字執(zhí)行順序的文章就介紹到這了,更多相關java static關鍵字執(zhí)行順序內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • java Quartz定時器任務與Spring task定時的幾種實現方法

    java Quartz定時器任務與Spring task定時的幾種實現方法

    本篇文章主要介紹了java Quartz定時器任務與Spring task定時的幾種實現方法的相關資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2017-02-02
  • Java語言描述存儲結構與鄰接矩陣代碼示例

    Java語言描述存儲結構與鄰接矩陣代碼示例

    這篇文章主要介紹了Java語言描述存儲結構與鄰接矩陣代碼示例,涉及Java存儲結構,鄰接矩陣,鄰接表的介紹與比較,然后分享了鄰接矩陣的Java實現等相關內容,具有一定借鑒價值,需要的朋友可以參考。
    2017-11-11
  • SpringBean和Controller實現動態(tài)注冊與注銷過程詳細講解

    SpringBean和Controller實現動態(tài)注冊與注銷過程詳細講解

    這篇文章主要介紹了SpringBean和Controller實現動態(tài)注冊與注銷過程,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧
    2023-02-02
  • spring容器啟動實現初始化某個方法(init)

    spring容器啟動實現初始化某個方法(init)

    這篇文章主要介紹了spring容器啟動實現初始化某個方法(init),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • 剖析Java中線程編程的概念

    剖析Java中線程編程的概念

    這篇文章主要介紹了Java中線程編程的概念,是Java入門學習中的基礎知識,需要的朋友可以參考下
    2015-09-09
  • 基于Mybatis的配置文件入門必看篇

    基于Mybatis的配置文件入門必看篇

    這篇文章主要介紹了Mybatis的配置文件入門,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • JAVA微信掃碼支付模式二線上支付功能實現以及回調

    JAVA微信掃碼支付模式二線上支付功能實現以及回調

    本篇文章主要介紹了JAVA微信掃碼支付模式二線上支付功能實現以及回調,這里整理了詳細的代碼,有需要的小伙伴可以參考下。
    2016-11-11
  • SpringBoot集成P6Spy實現SQL日志的記錄詳解

    SpringBoot集成P6Spy實現SQL日志的記錄詳解

    P6Spy是一個框架,它可以無縫地攔截和記錄數據庫活動,而無需更改現有應用程序的代碼。一般我們使用的比較多的是使用p6spy打印我們最后執(zhí)行的sql語句
    2022-11-11
  • java使用this調用構造函數的實現方法示例

    java使用this調用構造函數的實現方法示例

    這篇文章主要介紹了java使用this調用構造函數的實現方法,結合實例形式分析了java面向對象程序設計中函數調用相關操作技巧,需要的朋友可以參考下
    2019-08-08
  • Java集合Stack源碼詳解

    Java集合Stack源碼詳解

    java工具包中的Stack是繼承于Vector(矢量隊列)的,由于Vector是通過數組實現的,這就意味著,Stack也是通過數組實現的,而非鏈表。當然,我們也可以將LinkedList當作棧來使用!
    2018-05-05

最新評論

扎兰屯市| 丹棱县| 通江县| 正定县| 潍坊市| 淮滨县| 莱阳市| 曲靖市| 新丰县| 开原市| 乳山市| 鄂托克旗| 海晏县| 上饶县| 柘荣县| 丽江市| 新田县| 七台河市| 沂南县| 任丘市| 万山特区| 赤水市| 澜沧| 南雄市| 玉树县| 邓州市| 安龙县| 沙田区| 六盘水市| 三门峡市| 阳新县| 民权县| 兖州市| 手机| 德惠市| 七台河市| 新泰市| 侯马市| 永和县| 玛多县| 元阳县|