gmnon.cn-疯狂蹂躏欧美一区二区精品,欧美精品久久久久a,高清在线视频日韩欧美,日韩免费av一区二区

站長資訊網
最全最豐富的資訊網站

一次性帶你弄懂java中的static關鍵字

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

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

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種情況周志明》P359 "觸發類初始化的8種情況")觸發:

  • 使用 new 關鍵字實例化對象的時候

  • 讀取或設置一個類型的靜態字段(常量")除外)

  • 調用一個類型的靜態方法

  • 使用反射調用類的時候

  • 當初始化類的時候,如果發現父類還沒有進行過初始化,則先觸發其父類初始化

  • 虛擬機啟動時,會先初始化主類(包含main()方法的那個類)

  • 當初次調用 MethodHandle 實例時,初始化該 MethodHandle 指向的方法所在的類。

  • 如果接口中定義了默認方法(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的各種用法,下一篇就寫如何花式編寫單例模式。

贊(0)
分享到: 更多 (0)
?
網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
gmnon.cn-疯狂蹂躏欧美一区二区精品,欧美精品久久久久a,高清在线视频日韩欧美,日韩免费av一区二区
成人黄色一级大片| 欧美爱爱视频免费看| 99精品人妻少妇一区二区 | 永久免费黄色片| 中文字幕亚洲乱码| 国产免费中文字幕| 色乱码一区二区三区熟女| 爱豆国产剧免费观看大全剧苏畅| 四季av一区二区| 欧美一级特黄a| 免费成人黄色大片| 久久最新免费视频| 国产毛片久久久久久国产毛片| av在线免费观看国产| 九一国产精品视频| 色婷婷综合久久久久中文字幕 | 日韩精品在线视频免费观看| 精品人妻人人做人人爽| 精品少妇在线视频| wwwwww.色| 精品少妇人妻av一区二区| 乱熟女高潮一区二区在线| 欧日韩免费视频| 日本免费观看网站| 久久久国产精华液999999| 福利在线小视频| 91精品91久久久中77777老牛| 国产wwwxx| 91网站在线观看免费| 国产精品99久久免费黑人人妻| www.久久91| 尤物av无码色av无码| 亚洲xxx在线观看| 日韩极品视频在线观看| 婷婷六月天在线| 日本手机在线视频| 污污网站免费看| 美女黄色免费看| 中文字幕1234区| 欧美牲交a欧美牲交aⅴ免费真 | avav在线看| 中国一级黄色录像| 国产成人亚洲精品无码h在线| 污污的视频免费观看| 国产肥臀一区二区福利视频| 日本三级中文字幕在线观看| 男女啪啪网站视频| 波多野结衣家庭教师在线| 超碰在线免费av| 黄色一级视频片| 色黄视频免费看| www.xxx亚洲| 免费无遮挡无码永久视频| 91欧美一区二区三区| 日韩一区二区三区不卡视频| 无罩大乳的熟妇正在播放| 女人床在线观看| 日韩精品视频网址| 女同激情久久av久久| 天天干天天综合| 在线视频日韩一区 | 男人天堂新网址| 日本中文字幕观看| 黄色一级片免费的| av中文字幕网址| 一级淫片在线观看| 26uuu成人| 国产精品无码乱伦| www国产无套内射com| 国产欧美精品aaaaaa片| 日本大胆人体视频| 老太脱裤让老头玩ⅹxxxx| 精品久久久久久久久久中文字幕| 国产乱子伦精品无码专区| 免费人成自慰网站| 131美女爱做视频| 无码人妻丰满熟妇区毛片| 日韩中文字幕免费在线| 日本熟妇人妻中出| 天天操,天天操| 激情图片qvod| 5月婷婷6月丁香| 亚洲成色www.777999| 性生生活大片免费看视频| 亚洲AV无码成人精品一区| 日韩精品一区二区三区电影| 日韩极品视频在线观看| 日韩欧美黄色大片| 老司机av福利| 北条麻妃在线视频观看| 久热精品在线观看视频| 黄色成人在线免费观看| av免费在线播放网站| 在线播放免费视频| 亚洲熟妇av日韩熟妇在线| 制服丝袜中文字幕第一页 | 亚洲中文字幕久久精品无码喷水 | 久久综合色视频| 色播五月激情五月| 精品无码一区二区三区爱欲| 日本特黄a级片| 国产va亚洲va在线va| 国产色视频在线播放| 欧美精品自拍视频| 深夜做爰性大片蜜桃| 日本在线观看a| 日韩国产小视频| 午夜久久福利视频| 玩弄中年熟妇正在播放| 日本老太婆做爰视频| 9久久婷婷国产综合精品性色 | 97在线国产视频| 天天久久综合网| 午夜久久久精品| 国产福利视频在线播放| 野外做受又硬又粗又大视频√| 8x8x成人免费视频| 国产精品视频分类| 欧美成人精品欧美一级乱| 国产二区视频在线| 精品视频在线观看一区二区| 男人午夜视频在线观看| 亚洲免费看av| 欧美午夜性生活| 四季av一区二区| 免费黄色一级网站| 日本一极黄色片| 激情网站五月天| 无遮挡又爽又刺激的视频| 99色精品视频| 少妇人妻互换不带套| 成人黄色片视频| 亚洲一二三区av| 欧美第一页浮力影院| 色婷婷一区二区三区av免费看| av污在线观看| 图片区乱熟图片区亚洲| 视频一区二区视频| 国产一区 在线播放| 免费一级特黄特色毛片久久看| 欧美人成在线观看| 黄色片一级视频| 国产精品视频黄色| 亚洲 欧洲 日韩| www.好吊操| 一区二区三区国产免费| 国产原创精品在线| 一区二区三区四区久久| a级片一区二区| 岳毛多又紧做起爽| 日本中文字幕二区| www成人免费| 粗暴91大变态调教| 国内av免费观看| 国模无码视频一区二区三区| 午夜视频在线瓜伦| 国产精品88久久久久久妇女 | 污污网站免费观看| 日韩最新中文字幕| 欧美女人性生活视频| 日本不卡一区二区在线观看| 国产精品免费看久久久无码| 岳毛多又紧做起爽| 中文字幕在线乱| 国产91对白刺激露脸在线观看| 国产精品嫩草影院8vv8| 国产妇女馒头高清泬20p多| 一路向西2在线观看| 女人被男人躁得好爽免费视频 | 午夜久久久精品| 久久男人资源站| 欧美激情国内自拍| 大肉大捧一进一出好爽动态图| 天堂av8在线| 国产一区二区三区精彩视频| 欧美h视频在线观看| 黄色高清无遮挡| 成人性免费视频| 精品一区二区三区毛片| 亚洲天堂网一区| 日韩av资源在线| 天天做天天躁天天躁| 香蕉视频xxxx| 91pony九色| 中日韩av在线播放| 黄色在线视频网| 无码无遮挡又大又爽又黄的视频| 男女猛烈激情xx00免费视频| 伊人国产精品视频| 五月激情五月婷婷| 深夜黄色小视频| 久草在在线视频| 99视频精品免费| 欧洲熟妇精品视频| 青青青在线视频免费观看| 欧美大片在线播放| 欧美日韩亚洲一| 日日摸日日碰夜夜爽av | 天天干天天色天天干| 熟妇人妻无乱码中文字幕真矢织江 |