日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

c++模板类静态成员变量_一文讲透父子类中静态变量,成员变量初始化顺序原理...

發布時間:2023/12/9 c/c++ 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c++模板类静态成员变量_一文讲透父子类中静态变量,成员变量初始化顺序原理... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

推薦:

  • 從面試到入職到離職,我在B站工作的30天時光
  • 愛了愛了,Alibaba頂級MySQL調優手冊到手,加薪妥了
  • 愛了愛了,Spring Cloud Alibaba內部微服務架構筆記真的太牛了

本文主要是想分析一下靜態變量和成員變量的初始化順序,以及如果存在父類和子類關系時,這些變量的順序又是如何呢?本文將一一進行分析。

類加載初始化和實例對象初始化

首先我們要區分一個概念,那就是變量初始化也可以分為兩大類, 一類是Java虛擬機中的類加載機制內有一個初始化,而我們實例化一個對象(即通過new關鍵字)時也有一個對象實例的初始化。

首先我們要知道,一個類理論上不考慮內存影響的話可以被實例化無數次,所以我們想要實例化一個對象,那么就必須要有這個類,所有類加載一定在對象實例化前面。

而靜態變量是在類加載階段就會進行初始化的(如果想詳細了解Java虛擬機的類加載機制,可以點擊這里),故而如果在同一個類中,那么靜態變量的初始化一定在成員變量的初始化前面

靜態變量和成員變量區別

我們先來看下面兩句簡單的代碼:

package com.zwx.coreJava;public class InitVariable { public static int m = 1;//靜態變量(類變量) private int n = 2;//成員變量(實例變量) public static void main(String[] args) { System.out.println(InitVariable.m);//直接通過類訪問變量 InitVariable initVariable = new InitVariable();//創建一個實例對象 System.out.println(initVariable.n);//需要通過實例對象才能訪問成員變量 }}

其中m就是靜態變量,也稱之為類變量,類加載之后,存儲在方法區內,可以直接通過:類名.變量名進行調用。如:對象.m。

其中n就是成員變量,也稱之為實例變量,屬于對象實例,需要通過new一個對象之后才能引用。如:new 對象().n。成員變量的生命周期是和實例對象一致的,當實例對象被回收之后,對應的成員變量也消失了。

變量加載順序

加下來就讓我們一起結合例子驗證一下變量的加載順序

靜態變量和成員變量加載順序

首先我們建立一個父類,然后僅以父類為例子驗證下靜態變量和成員變量的加載順序:

package com.zwx.coreJava;public class SuperInitVariable { static String superStaticStr = "I'm Super Static Str1"; String superInstanceStr = "I'm Super Instance Str1"; static { superStaticStr = "I'm Super Static Str2"; } static { superStaticStr = "I'm Super Static Str3"; } public SuperInitVariable() { superInstanceStr = "I'm Super Instance Str2"; }}

然后新建一個測試類:

package com.zwx.coreJava;public class TestVariableOrder { public static void main(String[] args) { System.out.println(SuperInitVariable.superStaticStr); SuperInitVariable superInitVariable = new SuperInitVariable(); System.out.println(superInitVariable.superInstanceStr); }}

輸出結果:

I'm Super Static Str3I'm Super Instance Str2

很明顯,第一句話還沒有實例化對象就可以輸出靜態變量,所以靜態變量優先級最高,靜態代碼塊也是一樣會加載,多個代碼塊之間按先后順序加載。
第二句成員變量先初始化了變量,再執行了構造器。所以可以得出如下結論:

  • 1、靜態變量優先級最先被初始化,多個靜態代碼塊按代碼先后順序進行加載
  • 2、成員變量先賦值,再執行構造函數

父類和子類變量加載順序

將上面的父類簡單改造一下:

package com.zwx.coreJava;public class SuperInitVariable { static String superStaticStr = "I'm Super Static Str1"; String superInstanceStr = "I'm Super Instance Str1"; static { superStaticStr = "I'm Super Static Str2"; System.out.println("Super Static:" + superStaticStr); } public SuperInitVariable() { superInstanceStr = "I'm Super Instance Str2"; System.out.println("Super Construct:" + superStaticStr); }}

然后再新建一個子類,繼承上面的SuperInitVariable:

package com.zwx.coreJava;public class SubInitVariable extends SuperInitVariable { static String subStaticStr = "I'm Sub Static Str1"; String subInstanceStr = "I'm Sub Instance Str1"; static { subStaticStr = "I'm Sub Static Str2"; System.out.println("Sub Static:" + subStaticStr); } public SubInitVariable() { subInstanceStr = "I'm Sub Instance Str1"; System.out.println("Sub Construct:" + subInstanceStr); }}

然后在測試類中執行以下語句:

package com.zwx.coreJava;public class TestVariableOrder { public static void main(String[] args) { System.out.println(SubInitVariable.subStaticStr); }}

輸出如下結果:

Super Static:I'm Super Static Str2Sub Static:I'm Sub Static Str2I'm Sub Static Str2

可以很明顯看到加載順序為:先加載父類靜態變量,再加載子類靜態變量
接下來再改造下測試類,我們去實例化一個SubInitVariable對象實例:

package com.zwx.coreJava;public class TestVariableOrder { public static void main(String[] args) { SubInitVariable subInitVariable = new SubInitVariable(); }}

輸出結果如下:

Super Static:I'm Super Static Str2Sub Static:I'm Sub Static Str2Super Construct:I'm Super Static Str2Sub Construct:I'm Sub Instance Str1

可以很明顯的得出如下結論:

  • 1、初始化父類靜態變量。
  • 2、初始化子類靜態變量。
  • 3、初始化父類成員變量。
  • 4、加載父類構造器。
  • 5、初始化子類成員變量。
  • 6、加載子類構造器。

或者說可以分的更細致一點,可以總結為如下:

  • 1、初始化父類靜態變量。
  • 2、初始化父類靜態代碼塊。
  • 3、初始化子類靜態變量。
  • 4、初始化子類靜態代碼塊。
  • 5、初始化父類成員變量。
  • 6、加載父類構造器。
  • 7、初始化子類成員變量。
  • 8、加載子類構造器。

引用類加載順序

上面的例子中變量都是String類型的,那么假如變量是引用類型呢?又會怎么樣?
我們再來看個例子。新建兩個類,其中一個類引用另一個類:

package com.zwx.coreJava;public class ReferenceObj { static String referenceStaticStr; String referenceInstanceStr; static { referenceStaticStr = "I'm reference Static Str"; System.out.println(referenceStaticStr); } public ReferenceObj() { referenceInstanceStr = "I'm reference Construct Str"; System.out.println(referenceInstanceStr); }}package com.zwx.coreJava;public class InitReferenceVariable { static ReferenceObj staticObj; ReferenceObj obj; static { System.out.println("static code:" + staticObj); } public InitReferenceVariable() { System.out.println("construct code:" + obj); }}

上面例子中看到,我們只是持有了另一個對象的引用,不做任何初始化動作,這時候是否會去加載引用類呢?我們新建一個測試類測試一下:

package com.zwx.coreJava;public class TestVariableOrder { public static void main(String[] args) { //測試引用變量和數組 System.out.println(InitReferenceVariable.staticObj); InitReferenceVariable initReferenceVariable = new InitReferenceVariable(); System.out.println(initReferenceVariable.obj); }}

輸出如下結果:

static code:nullnullconstruct code:nullnull

可以看到,引用類ReferenceObj沒有被實例化也沒有被加載。
那么我們把上面的變量進行初始化修改一下:

static ReferenceObj staticObj = new ReferenceObj();ReferenceObj obj = new ReferenceObj();

再次運行測試類,輸出如下結果:

I'm reference Static StrI'm reference Construct Strstatic code:com.zwx.coreJava.ReferenceObj@4b1210eecom.zwx.coreJava.ReferenceObj@4b1210eeI'm reference Construct Strconstruct code:com.zwx.coreJava.ReferenceObj@4d7e1886

可以看到:I’m reference Static Str只輸出了1次,而I’m reference Construct Str輸出了2次,這是因為同一個類只會被加載1次,但是我們new了兩次,也就是實例化了2次,所以構造函數會執行2次。
根據這個結果我們可以得出如下結論:

  • 1、一個類假如只是引用另一個類而沒有被實例化,那么不會觸發引用類的類加載和實例化
  • 1、一個類假如引用另一個類并且實例化了引用類,那么會優先加載引用類和實例化引用類

數組引用類加載順序

把類改造如下:

package com.zwx.coreJava;public class InitReferenceVariable { static ReferenceObj[] arr = new ReferenceObj[10];}

然后在測試類中輸出如下語句:

System.out.println("輸出數組:" + InitReferenceVariable.arr);

輸出結果如下:

輸出數組:[Lcom.zwx.coreJava.ReferenceObj;@4b1210ee

可以看到只會輸出這一句話,而不會觸發ReferenceObj的類加載和初始化。
可以得出如下結論:
如果將引用類作為數組對象,那么創建數組的時候不會觸發數組對象的類加載和初始化

總結

本文從父類,子類,引用類,以及數組引用類的角度全面分析了什么時候會觸發一個類的加載,什么時候會觸發一個類的實例化。而一個類在加載的時候就會初始化靜態變量,一個類在實例化的時候就會觸發成員變量的初始化。本文涉及到類加載時并沒有特別深入的介紹,有興趣的,可以看下本人下的JVM虛擬機系列2中講述的類加載機制,相信看完之后會有更加深刻的理解和體會。

來源:http://002ii.cn/?T0vKxr

總結

以上是生活随笔為你收集整理的c++模板类静态成员变量_一文讲透父子类中静态变量,成员变量初始化顺序原理...的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。