標籤:類變數(靜態變數)、執行個體變數(非靜態變數)、靜態代碼塊、非靜態代碼塊
Java代碼初始化順序:
1.由 static 關鍵字修飾的(如:類變數[靜態變數]、靜態代碼塊)將在類被初始化建立執行個體對象之前被初始化,而且是按順序從上到下依次被執行。靜態(類變數、靜態代碼塊)屬於類本身,不依賴於類的執行個體。
2.沒有 static 關鍵字修飾的(如:執行個體變數[非靜態變數]、非靜態代碼塊)初始化實際上是會被提取到類的構造器中被執行的,但是會比類構造器中的代碼塊優先執行到,非靜態(執行個體變數、非靜態代碼塊)的地位是相等的,它們將按順序被執行。
形參:
比如你定義一個函數void add(int a, int b),這裡的a和b就是形參。
當你進行函數調用的時候,add(1, 2),這裡的1和2就是實參。
向前引用:
所謂向前引用,就是在定義類、介面、方法、變數之前使用它們。
成員變數:
在類體裡面定義的變數稱為成員變數;
如果該成員變數有 static 關鍵字修飾,則該成員變數稱為 靜態變數 或 類變數;
如果該成員變數沒有 static 關鍵字修飾,則該成員變數被稱為 非靜態變數 或 執行個體變數。
局部變數:
形參、方法內定義的變數、代碼塊中定義的變數,都屬於局部變數。
類變數 (靜態變數)
1. 可以向前引用
2. 變數屬於類本身
3. 類變數不依賴類的執行個體,類變數只在初始化時候在方法區中被分配一次空間,無論類的執行個體被建立幾次,都不再為類變數分配空間
4. 通過類的任意一個執行個體來訪問類變數,底層都將將其轉為通過類本身來訪問類變數,它們的效果是一樣的
5. 一旦類變數的值被改變,通過類或類的任意一個執行個體來訪問類變數,得到的都將是被改變後的值
6. 將在類的初始化之前初始化
執行個體變數(非靜態變數)
1. 不能向前引用,如果向前引用,則稱為非法向前引用,這是不允許的
2. 變數屬於類的執行個體對象
3. 隨著類的執行個體被建立而分配記憶體空間
非靜態代碼塊
直接由 { } 包起來的代碼,稱為非靜態代碼塊
靜態代碼塊
直接由 static { } 包起來的代碼,稱為靜態代碼塊
類變數(靜態變數)、執行個體變數(非靜態變數)、靜態代碼塊、非靜態代碼塊的初始化時機
由 static 關鍵字修飾的(如:類變數[靜態變數]、靜態代碼塊)將在類被初始化建立執行個體對象之前被初始化,而且是按順序從上到下依次被執行;
沒有 static 關鍵字修飾的(如:執行個體變數[非靜態變數]、非靜態代碼塊)初始化實際上是會被提取到類的構造器中被執行的,但是會比類構造器中的 代碼塊優先執行到,其也是按順序從上到下依次被執行。
範例程式碼:
public class Statical { /** * 靜態代碼塊 類變數(靜態變數)可以向前引用(即:先引用,再定義) */ static { name = "fancydeepin"; // name 的定義在使用之後 System.out.println("---> 靜態代碼塊被執行 <---"); } /** * 類變數(靜態變數)在類的初始化之前初始化,無論類的執行個體將被建立多少個 凡 static修飾的,都將按位置被順序執行,所以, name * 的值最終輸出 fancy 而不是上面的 fancydeepin */ public static String name = "fancy"; // 類變數(靜態變數) private String mail = "myEmail"; // 執行個體變數(非靜態變數),定義時指定初始值,會比在構造器賦予值更早執行 public Statical() { mail = "[email protected]"; System.out.println("---> 構造器代碼塊被執行 <---"); } /** * 非靜態代碼塊 實際上,非靜態代碼塊在類初始化建立執行個體時,將會被提取到類的構造器中, 但是,非靜態代碼塊會比構造器中的代碼塊優先被執行 * 所以,mail 最終輸出的是類構造器中給定的值,也就是 [email protected] 而不是 * [email protected],更不是 myEmail */ { mail = "[email protected]"; System.out.println("---> 非靜態代碼塊被執行 <---"); } public static void main(String[] args) { Statical statical = new Statical(); System.out.println(name); System.out.println(statical.mail); }}
輸出結果:
---> 靜態代碼塊被執行 <---
---> 非靜態代碼塊被執行 <---
---> 構造器代碼塊被執行 <---
fancy
[email protected]
容易混淆的一個知識點
靜態方法只允許直接訪問靜態成員,而執行個體方法中可以訪問靜態成員和執行個體成員,原因是類還沒有執行個體化,所執行個體成員也沒有被建立,靜態方法中因此也不能用this。
錯誤:class A{private int a;static void f(){a=1;}}正確:private static int a;static void f(){a=1;}}
當然靜態方法可以通過對象間接訪問非靜態成員的
public static void main(String[] args) { Statical statical = new Statical(); System.out.println(name); System.out.println(statical.mail); }
在靜態方法main中name是靜態變數可以直接存取,而mail屬於非靜態態變數,System.out.println(mail)直接存取會報錯,必須通過執行個體對象statical間接訪問。
本文出自 “一無所有-天行者” 部落格,請務必保留此出處http://tianxingzhe.blog.51cto.com/3390077/1656302
Java基礎-代碼執行順序(重要)