fancydeepin前言:這屬於 java 的基礎知識,你可以不瞭解,也可以不拿它當一回事,代碼也一樣能敲的順暢;這是很久之前,我從 C++ 轉 java 剛入門那會的看法,那會我堅持自己的理念:
重實踐,講運用,輕理論。當然,對同一樣事物,在不同階段也會有不一樣的看法,這理念在某個時段已經不適合我,早就被拋棄瞭。不扯淡瞭,直接進入主題。
java 中的變量大致分為 成員變量 和 局部變量 兩大類。
成員變量:
在類體裡面定義的變量稱為成員變量;
如果該成員變量有 static 關鍵字修飾,則該成員變量稱為 靜態變量 或 類變量;
如果該成員變量沒有 static 關鍵字修飾,則該成員變量被稱為 非靜態變量 或 實例變量。
局部變量:
形參、方法內定義的變量、代碼塊中定義的變量,都屬於局部變量。
類變量 (靜態變量)
1. 可以向前引用
2. 變量屬於類本身
3. 類變量不依賴類的實例,類變量隻在初始化時候在棧內存中被分配一次空間,無論類的實例被創建幾次,都不再為類變量分配空間
4. 通過類的任意一個實例來訪問類變量,底層都將將其轉為通過類本身來訪問類變量,它們的效果是一樣的
5. 一旦類變量的值被改變,通過類或類的任意一個實例來訪問類變量,得到的都將是被改變後的值
6. 將在類的初始化之前初始化
實例變量(非靜態變量)
1. 不能向前引用,如果向前引用,則稱為非法向前引用,這是不允許的
2. 變量屬於類的實例對象
3. 隨著類的實例被創建而分配內存空間
非靜態代碼塊
直接由 { } 包起來的代碼,稱為非靜態代碼塊
靜態代碼塊
直接由 static { } 包起來的代碼,稱為靜態代碼塊
類變量(靜態變量)、實例變量(非靜態變量)、靜態代碼塊、非靜態代碼塊 的初始化時機
由 static 關鍵字修飾的(如:類變量[靜態變量]、靜態代碼塊)將在類被初始化創建實例對象之前被初始化,而且是按順序從上到下依次被執行;
沒有 static 關鍵字修飾的(如:實例變量[非靜態變量]、非靜態代碼塊)初始化實際上是會被提取到類的構造器中被執行的,但是會比類構造器中的
代碼塊優先執行到,其也是按順序從上到下依次被執行。
– 以上是本人在翻完 PDF 後的個人筆記和理解以及見解,不見得百分百對,以下附上本人測試示例代碼,會更有說服性
示例代碼
1
2/**
3 * —————————————–
4 * @文件: Statical.java
5 * @作者: fancy
6 * @郵箱: fancydeepin@yeah.net
7 * @時間: 2012-7-9
8 * @描述: TEST
9 * —————————————–
10 */
11public class Statical {
12
13 /**
14 * 靜態代碼塊
15 * 類變量(靜態變量)可以向前引用(即:先引用,再定義)
16 */
17 static {
18 name = "fancydeepin"; // name 的定義在使用之後
19 System.out.println("—> 靜態代碼塊被執行 <—");
20 }
21 /**
22 * 類變量(靜態變量)在類的初始化之前初始化,無論類的實例將被創建多少個
23 * 類變量(靜態變量)都將隻在初始化時候在棧內存上分配一次空間
24 * 凡 static 修飾的,都將按位置被順序執行,所以,
25 * name 的值最終輸出 fancy 而不是上面的 fancydeepin
26 */
27 public static String name = "fancy"; //類變量(靜態變量)
28 private String mail = "myEmail"; //實例變量(非靜態變量),定義時指定初始值,會比在構造器賦予值更早執行
29
30 public Statical() {
31 mail = www.aiwalls.com;
32 System.out.println("—> 構造器代碼塊被執行 <—");
33 }
34 /**
35 * 非靜態代碼塊
36 * 實際上,非靜態代碼塊在類初始化創建實例時,將會被提取到類的構造器中,
37 * 但是,非靜態代碼塊會比構造器中的代碼塊優先被執行
38 * 所以,mail 最終輸出的是類構造器中給定的值,也就是 www.aiwalls.com
39 * 而不是 www.aiwalls.com,更不是 myEmail
40 */
41 {
42 mail = "www.aiwalls.com";
43 System.out.println("—> 非靜態代碼塊被執行 <—");
44 }
45
46 // getting and setting
47
測試類示例代碼
1
2 /**
3 * 類變量(靜態變量)在類被初始化創建實例之前被初始化
4 */
5 System.out.println("—————–> @1 <—————-");
6 System.out.println("name —>> " + Statical.name); // @1
7 System.out.println("—————–> @1 <—————-");
8 /**
9 * 創建類的實例對象
10 */
11 System.out.println("—————–> @6 <—————-");
12 Statical statical = new Statical(); // @6
13 System.out.println("—————–> @6 <—————-");
14 /**
15 * 通過實例來訪問類變量,底層將轉化成通過類本身來訪問類變量
16 */
17 System.out.println("—————–> @2 <—————-");
18 System.out.println("name —>> " + statical.name); // @2
19 System.out.println("—————–> @2 <—————-");
20 /**
21 * 如果類變量的值被改變,再訪問類變量,將得到被改變後的值
22 */
23 Statical.name = "fancydeepin";
24
25 System.out.println("—————–> @3 <—————-");
26 System.out.println("name —>> " + statical.name); // @3
27 System.out.println("—————–> @3 <—————-");
28
29 System.out.println("—————–> @4 <—————-");
30 System.out.println("name —>> " + Statical.name); // @4
31 System.out.println("—————–> @4 <—————-");
32 /**
33 * 非靜態代碼塊 和 構造器 被執行的時機
34 */
35 System.out.println("—————–> @5 <—————-");
36 System.out.println("mail —>> " + statical.getMail()); // @5
37 System.out.println("—————–> @5 <—————-");
38
後臺輸出結果
—————–> @1 <—————-
—> 靜態代碼塊被執行 <—
name —>> fancy
—————–> @1 <—————-
—————–> @6 <—————-
—> 非靜態代碼塊被執行 <—
—> 構造器代碼塊被執行 <—
—————–> @6 <—————-
—————–> @2 <—————-
name —>> fancy
—————–> @2 <—————-
—————–> @3 <—————-
name —>> fancydeepin
—————–> @3 <—————-
—————–> @4 <—————-
name —>> fancydeepin
—————–> @4 <—————-
—————–> @5 <—————-
mail —>> fancydeepin@yeah.net
—————–> @5 <—————-
作者:fancydeepin