Java代碼初始化順序:
java
1.由 static 關鍵字修飾的(如:類變量(靜態變量)、靜態代碼塊)將在類被初始化建立實例對象以前被初始化,並且是按順序從上到下依次被執行。靜態(類變量、靜態代碼塊)屬於類自己,不依賴於類的實例。ide
2.沒有 static 關鍵字修飾的(如:實例變量(非靜態變量)、非靜態代碼塊)初始化其實是會被提取到類的構造器中被執行的,可是會比類構造器中的代碼塊優先執行到,非靜態(實例變量、非靜態代碼塊)的地位是相等的,它們將按順序被執行。
函數
形參:this
好比你定義一個函數void add(int a, int b),這裏的a和b就是形參。spa
當你進行函數調用的時候,add(1, 2),這裏的1和2就是實參。.net
向前引用:對象
所謂向前引用,就是在定義類、接口、方法、變量以前使用它們。接口
成員變量:
在類體裏面定義的變量稱爲成員變量;
若是該成員變量有 static 關鍵字修飾,則該成員變量稱爲 靜態變量 或 類變量;
若是該成員變量沒有 static 關鍵字修飾,則該成員變量被稱爲 非靜態變量 或 實例變量。
局部變量:
形參、方法內定義的變量、代碼塊中定義的變量,都屬於局部變量。
類變量 (靜態變量)
1. 能夠向前引用
2. 變量屬於類自己
3. 類變量不依賴類的實例,類變量只在初始化時候在方法區中被分配一次空間,不管類的實例被建立幾回,都再也不爲類變量分配空間
4. 經過類的任意一個實例來訪問類變量,底層都將將其轉爲經過類自己來訪問類變量,它們的效果是同樣的
5. 一旦類變量的值被改變,經過類或類的任意一個實例來訪問類變量,獲得的都將是被改變後的值
6. 將在類的初始化以前初始化
實例變量(非靜態變量)
1. 不能向前引用,若是向前引用,則稱爲非法向前引用,這是不容許的
2. 變量屬於類的實例對象
3. 隨着類的實例被建立而分配內存空間
非靜態代碼塊
直接由 { } 包起來的代碼,稱爲非靜態代碼塊
靜態代碼塊
直接由 static { } 包起來的代碼,稱爲靜態代碼塊
類變量(靜態變量)、實例變量(非靜態變量)、靜態代碼塊、非靜態代碼塊的初始化時機
由 static 關鍵字修飾的(如:類變量[靜態變量]、靜態代碼塊)將在類被初始化建立實例對象以前被初始化,並且是按順序從上到下依次被執行;
沒有 static 關鍵字修飾的(如:實例變量[非靜態變量]、非靜態代碼塊)初始化其實是會被提取到類的構造器中被執行的,可是會比類構造器中的 代碼塊優先執行到,其也是按順序從上到下依次被執行。內存
示例代碼:ci
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 = "fancydeepin@yeah.net"; System.out.println("---> 構造器代碼塊被執行 <---"); } /** * 非靜態代碼塊 實際上,非靜態代碼塊在類初始化建立實例時,將會被提取到類的構造器中, 可是,非靜態代碼塊會比構造器中的代碼塊優先被執行 * 因此,mail 最終輸出的是類構造器中給定的值,也就是 fancydeepin@yeah.net 而不是 * 1525336367@qq.com,更不是 myEmail */ { mail = "1525336367@qq.com"; System.out.println("---> 非靜態代碼塊被執行 <---"); } public static void main(String[] args) { Statical statical = new Statical(); System.out.println(name); System.out.println(statical.mail); } }
輸出結果:
---> 靜態代碼塊被執行 <---
---> 非靜態代碼塊被執行 <---
---> 構造器代碼塊被執行 <---
fancy
fancydeepin@yeah.net
容易混淆的一個知識點
靜態方法只容許直接訪問靜態成員,而實例方法中能夠訪問靜態成員和實例成員,緣由是類尚未實例化,所實例成員也沒有被建立,靜態方法中所以也不能用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間接訪問。