欧美亚洲自拍偷拍_日本一区视频在线观看_国产二区在线播放_亚洲男人第一天堂

二維碼
企資網

掃一掃關注

當前位置: 首頁 » 企業資訊 » 資訊 » 正文

一題搞定static關鍵字

放大字體  縮小字體 發布日期:2021-09-05 06:33:58    作者:企資小編    瀏覽次數:97
導讀

基礎不牢,地動山搖。大家好,我是課代表。可以關注我的公眾號:Java課代表,原創實戰干貨首發地兒,等你呦。開篇一道題,考察代碼執行順序:public class Parent {static {System.out.println("Parent static i

基礎不牢,地動山搖。

大家好,我是課代表。可以關注我的公眾號:Java課代表,原創實戰干貨首發地兒,等你呦。

開篇一道題,考察代碼執行順序:

public class Parent {    static {        System.out.println("Parent static initial block");    }    {        System.out.println("Parent initial block");    }    public Parent() {        System.out.println("Parent constructor block");    }}public class Child extends Parent {    static {        System.out.println("Child static initial block");    }    {        System.out.println("Child initial block");    }        private Hobby hobby = new Hobby();    public Child() {        System.out.println("Child constructor block");    }}public class Hobby {    static{        System.out.println("Hobby static initial block");    }    public Hobby() {        System.out.println("hobby constructor block");    }}

當執行new Child()時,上述代碼輸出什么?

相信有不少同學遇到過這類問題,可能查過資料之后接著就忘了,再次遇到還是答不對。接下來課代表通過4個步驟,帶大家拆解一下這段代碼的執行順序,并借此總結規律。

1.編譯器優化了啥?

下面兩段代碼對比一下編譯前后的變化:

編譯前的Child.java

public class Child extends Parent {    static {        System.out.println("Child static initial block");    }    {        System.out.println("Child initial block");    }        private Hobby hobby = new Hobby();        public Child() {        System.out.println("Child constructor block");    }}

編譯后的Child.class

public class Child extends Parent {    private Hobby hobby;    public Child() {        System.out.println("Child initial block");        this.hobby = new Hobby();        System.out.println("Child constructor block");    }    static {        System.out.println("Child static initial block");    }}

通過對比可以看到,編譯器把初始化塊和實例字段的賦值操作,移動到了構造函數代碼之前,并且保留了相關代碼的先后順序。事實上,如果構造函數有多個,初始化代碼也會被復制多份移動過去。

據此可以得出第一條優先級順序:

  • 初始化代碼 > 構造函數代碼

    2.static 有啥作用?

    類的加載過程可粗略分為三個階段:加載 -> 鏈接 -> 初始化

    初始化階段可被8種情況觸發:

    1. 使用 new 關鍵字實例化對象的時候
    2. 讀取或設置一個類型的靜態字段(常量除外)
    3. 調用一個類型的靜態方法
    4. 使用反射調用類的時候
    5. 當初始化類的時候,如果發現父類還沒有進行過初始化,則先觸發其父類初始化
    6. 虛擬機啟動時,會先初始化主類(包含main()方法的那個類)
    7. 當初次調用 MethodHandle 實例時,初始化該 MethodHandle 指向的方法所在的類。
    8. 如果接口中定義了默認方法(default 修飾的接口方法),該接口的實現類發生了初始化,則該接口要在其之前被初始化

    其中的2,3條目是被static代碼觸發的。

    其實初始化階段就是執行類構造器<clinit> 方法的過程,這個方法是編譯器自動生成的,里面收集了static修飾的所有類變量的賦值動作和靜態語句塊(static{} 塊),并且保留這些代碼出現的先后順序。

    根據條目5,JVM 會保證在子類的<clinit>方法執行前,父類的<clinit>方法已經執行完畢。

    小結一下:訪問類變量或靜態方法,會觸發類的初始化,而類的初始化就是執行<clinit>,也就是執行 static 修飾的賦值動作和static{}塊,并且 JVM 保證先執行父類初始化,再執行子類初始化。

    由此得出第二條優先級順序:

  • 父類的static代碼 > 子類的static代碼

    3.static 代碼只執行一次

    我們都知道,static代碼(靜態方法除外)只執行一次。

    你有沒有想過,這個機制是如何保證的呢?

    答案是:雙親委派模型。

    JDK8 及之前的雙親委派模型是:

    應用程序類加載器 → 擴展類加載器 → 啟動類加載器

    平時開發中寫的類,默認都是由 應用程序類加載器加載,它會委派給其父類:擴展類加載器。而擴展類加載器又會委派給其父類:啟動類加載器。只有當父類加載器反饋無法完成這個加載請求時,子加載器才會嘗試自己去完成加載,這個過程就是雙親委派。三者的父子關系并不是通過繼承,而是通過組合模式實現的。

    該過程的實現也很簡單,下面展示關鍵實現代碼:

    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException{    // 首先檢查該類是否被加載過    // 如果加載過,直接返回該類    Class<?> c = findLoadedClass(name);    if (c == null) {        try {            if (parent != null) {                c = parent.loadClass(name, false);            } else {                c = findBootstrapClassOrNull(name);            }        } catch (ClassNotFoundException e) {            // 如果父類拋出ClassNotFoundException            // 說明父類無法完成加載請求        }        if (c == null) {            // 如果父類無法加載,轉由子類加載            c = findClass(name);        }    }    if (resolve) {        resolveClass(c);    }    return c;}

    結合注釋相信大家很容易看懂。

    由雙親委派的代碼可知,同一個類加載器下,一個類只能被加載一次,也就限定了它只能被初始化一次。所以類中的 static代碼(靜態方法除外)只在類初始化時執行一次

    4. <init>和<clinit>

    前面已經介紹了編譯器自動生成的類構造器:<clinit>方法,它會收集static修飾的所有類變量的賦值動作和靜態語句塊(static{} 塊)并保留代碼的出現順序,它會在類初始化時執行

    相應的,編譯器還會生成一個<init>方法,它會收集實例字段的賦值動作、初始化語句塊({}塊)和構造器(Constructor)中的代碼,并保留代碼的出現順序,它會在 new 指令之后接著執行

    所以,當我們new 一個類時,如果JVM未加載該類,則先對其進行初始化,再進行實例化。

    至此,第三條優先級規則也就呼之欲出了:

  • 靜態代碼(static{}塊、靜態字段賦值語句) > 初始化代碼({}塊、實例字段賦值語句)

    5. 規律實踐

    將前文的三條規則合并,總結出如下兩條:

    1.靜態代碼(static{}塊、靜態字段賦值語句) > 初始化代碼({}塊、實例字段賦值語句) > 構造函數代碼

    2.父類的static代碼 > 子類的static代碼

    根據前文總結,初始化代碼和構造函數代碼被編譯器收集到了<init>中,靜態代碼被收集到了<clinit>中,所以再次對上述規律做合并:

    父類<clinit> > 子類<clinit> > 父類 <init> > 子類 <init>

    對應到開篇的問題,我們來實踐一下:

    當執行new Child()時,new關鍵字觸發了 Child 類的初始化 ,JVM 發現其有父類,則先初始化 Parent 類,開始執行Parent類的<clinit>方法,然后執行 Child 類的<clinit>方法(還記得<clinit>里面收集了什么嗎?)。

    然后開始實例化 一個Child類的對象,此時準備執行 Child 的<init>方法,發現它有父類,優先執行父類的<init>方法,然后再執行子類的<init>(還記得<init>里面收集了什么嗎?)。

    相信看到這里,各位心中已經對開篇的問題有答案了,不妨先手寫一下輸出順序,然后寫代碼親自驗證一下。

    結束語

    平時開發中經常用到static,每次寫的時候,心里總會打兩個問號,我為什么要用static?不用行不行?這正應了開篇的第一句話:

    基礎不牢,地動山搖

    通過本文可以看出,static的應用遠遠不止類變量,靜態方法那么簡單。在經典的單例模式中,你將看到static的各種用法,下一篇就寫如何花式編寫單例模式。


    原創碼字不容易,歡迎關注點贊和分享。

  •  
    (文/企資小編)
    免責聲明
    本文僅代表作發布者:企資小編個人觀點,本站未對其內容進行核實,請讀者僅做參考,如若文中涉及有違公德、觸犯法律的內容,一經發現,立即刪除,需自行承擔相應責任。涉及到版權或其他問題,請及時聯系我們刪除處理郵件:weilaitui@qq.com。
     

    Copyright ? 2016 - 2025 - 企資網 48903.COM All Rights Reserved 粵公網安備 44030702000589號

    粵ICP備16078936號

    微信

    關注
    微信

    微信二維碼

    WAP二維碼

    客服

    聯系
    客服

    聯系客服:

    在線QQ: 303377504

    客服電話: 020-82301567

    E_mail郵箱: weilaitui@qq.com

    微信公眾號: weishitui

    客服001 客服002 客服003

    工作時間:

    周一至周五: 09:00 - 18:00

    反饋

    用戶
    反饋

    欧美亚洲自拍偷拍_日本一区视频在线观看_国产二区在线播放_亚洲男人第一天堂

          9000px;">

                同产精品九九九| 日韩中文欧美在线| 久久精品国产一区二区三| 91精品国产乱| 精品一区二区在线观看| 久久女同互慰一区二区三区| 国产老肥熟一区二区三区| 久久久亚洲国产美女国产盗摄 | 欧美一级一级性生活免费录像| 天天色综合成人网| 日韩欧美激情在线| www.亚洲色图.com| 天天综合天天做天天综合| 久久先锋影音av鲁色资源网| 99九九99九九九视频精品| 亚洲一区二区三区国产| 久久亚洲影视婷婷| 日本乱人伦aⅴ精品| 日本不卡1234视频| 日韩一区日韩二区| 日韩欧美的一区二区| 99精品国产99久久久久久白柏 | 国产精品国产精品国产专区不片| 色婷婷综合久久久中文字幕| 男女男精品视频网| 亚洲日本韩国一区| 国产欧美精品一区| 在线播放中文字幕一区| 成人精品gif动图一区| 免费看欧美女人艹b| 一区二区三区高清不卡| 久久久久久久国产精品影院| 欧美日韩一级二级| 99re热这里只有精品免费视频| 麻豆成人综合网| 亚洲人123区| 欧美激情一区二区三区蜜桃视频| 91麻豆精品国产91久久久资源速度| 国产69精品一区二区亚洲孕妇 | 亚洲小少妇裸体bbw| 中文av一区二区| 日韩免费视频线观看| 欧美日本精品一区二区三区| 色8久久人人97超碰香蕉987| 成人自拍视频在线| 国产精品一区在线观看你懂的| 日韩精品一区第一页| 夜夜爽夜夜爽精品视频| 国产女人18水真多18精品一级做| 日韩欧美国产午夜精品| 欧美一区在线视频| 欧美久久久久久蜜桃| 欧美日韩一区高清| 欧美视频中文字幕| 欧美吻胸吃奶大尺度电影| 色综合久久天天综合网| 欧美在线制服丝袜| 在线视频你懂得一区| 欧美午夜宅男影院| 884aa四虎影成人精品一区| 欧美日韩国产不卡| 欧美精品久久一区| 精品久久久久久久久久久久久久久久久 | 在线看国产一区二区| 99re这里只有精品首页| 99国产精品久久久久久久久久| 成人午夜视频网站| 99国产精品久久久久久久久久| 波多野结衣精品在线| av网站免费线看精品| 91蝌蚪国产九色| 欧美日韩国产一级| 日韩一区二区高清| 日韩午夜激情免费电影| 欧美日韩精品二区第二页| 精品视频资源站| 欧美网站一区二区| 日韩免费高清电影| 日本一区二区三级电影在线观看| 欧美一区二区美女| 久久精品网站免费观看| 日本一区二区三区国色天香 | 欧美午夜理伦三级在线观看| 欧美猛男gaygay网站| 欧美日韩美女一区二区| 欧美一级片在线观看| 中文字幕欧美日本乱码一线二线| 久久影视一区二区| 中文字幕一区二区三中文字幕| 国产精品美女久久福利网站| 亚洲精品亚洲人成人网| 一区二区在线观看免费视频播放 | 欧美电影免费观看高清完整版| 日韩免费性生活视频播放| 久久久久国产精品麻豆ai换脸| 中文字幕在线观看一区| 亚洲一区二区三区四区五区黄| 麻豆精品一区二区三区| 国产成人aaaa| 一本大道av伊人久久综合| 欧美精品在线观看播放| 国产午夜精品久久久久久久| 一区二区在线看| 国产成人久久精品77777最新版本| 粉嫩av一区二区三区| 欧美日韩国产首页在线观看| 亚洲精品一区二区三区香蕉| 成人免费在线视频| 久久国产视频网| 91麻豆免费在线观看| 精品对白一区国产伦| 亚洲三级在线免费| 夫妻av一区二区| 69堂成人精品免费视频| 亚洲欧美在线aaa| 久久福利视频一区二区| 一本色道久久综合亚洲91| 久久综合九色综合97_久久久| 有坂深雪av一区二区精品| 国产激情视频一区二区在线观看| 欧美色图激情小说| 日韩美女视频一区二区 | 久久久久久黄色| 五月婷婷久久综合| av不卡在线观看| 国产精品视频看| 国精产品一区一区三区mba视频| 欧美亚洲一区二区在线观看| 亚洲色图一区二区| 成人精品一区二区三区四区 | 一区二区三区四区在线免费观看| 国产成人精品免费一区二区| 日韩三级电影网址| 日本中文在线一区| 欧美日韩黄视频| 亚洲综合免费观看高清完整版| 99视频在线观看一区三区| 国产精品污网站| 粉嫩高潮美女一区二区三区| 久久嫩草精品久久久精品一| 免费成人在线播放| 精品国产乱码久久久久久影片| 精品伊人久久久久7777人| 欧美大度的电影原声| 免费观看30秒视频久久| 日韩一区二区三区三四区视频在线观看| 亚洲综合成人在线视频| 欧美最猛黑人xxxxx猛交| 亚洲一区中文在线| 欧美色视频在线| 国内精品自线一区二区三区视频| 欧美zozozo| 国产成人精品午夜视频免费| 亚洲欧洲www| 91免费国产在线| 亚洲国产精品一区二区www| 欧美日韩专区在线| 奇米色一区二区| 中文在线免费一区三区高中清不卡 | 国产三级一区二区| 99国产精品国产精品毛片| 一区二区三区四区高清精品免费观看 | 亚洲综合清纯丝袜自拍| 欧美乱熟臀69xxxxxx| 激情小说亚洲一区| 国产精品久久免费看| 欧美性大战久久久久久久蜜臀 | 91精品欧美福利在线观看| 日本欧美在线看| 中日韩免费视频中文字幕| 91久久精品国产91性色tv| 男人的j进女人的j一区| 国产精品丝袜黑色高跟| 欧美在线观看一区| 国产精品一区二区在线看| 亚洲精品欧美专区| 精品国产免费人成在线观看| av高清不卡在线| 免费在线观看成人| 17c精品麻豆一区二区免费| 欧美一级生活片| 91啪九色porn原创视频在线观看| 亚洲成va人在线观看| 中文字幕在线观看不卡| 日韩亚洲欧美一区二区三区| eeuss国产一区二区三区| 男女男精品视频网| 亚洲视频每日更新| 精品99999| 欧美另类videos死尸| www.成人在线| 国内精品不卡在线| 精品亚洲成av人在线观看| 亚洲一区二区av电影| 国产亚洲va综合人人澡精品| 欧美撒尿777hd撒尿| a美女胸又www黄视频久久| 日本怡春院一区二区| 亚洲精品免费电影| 中文字幕欧美激情一区|