理解Java中的靜態域、程式碼塊和記憶體區域圖
阿新 • • 發佈:2019-02-11
Java面向物件(二) 靜態域、程式碼塊和記憶體區域圖
靜態域
- 將域定義成
static
後,每個類
中只有一個
這樣的域,與類相關的,也稱為類成員
。但是每個物件
對於所有的例項域
卻都有自己的一份拷貝
。 靜態域
會隨著類的載入而載入並初始化
,存在於方法區記憶體中
的位元組碼檔案的靜態區域
中。優先於物件存在
,先有方法區的類載入,後才可能會有堆記憶體的物件例項化。- 靜態域會
被所有的物件共享
,也稱為共享區。 - 一般
共性用靜態
,特性用非靜態。 - 一般通過
類名直接呼叫
,雖然也可以
通過物件名
呼叫,但是不推薦
,也不合適。
static關鍵字注意事項
- 在靜態方法中沒有this關鍵字
- 靜態是隨著類的載入而初始化,而
this
隨著物件的建立而存在
的。 - 靜態比物件優先存在。
- 靜態是隨著類的載入而初始化,而
- 靜態方法只能訪問靜態成員和靜態成員方法,即
靜態只能訪問靜態
- 靜態方法:
- 成員變數:只能訪問靜態變數
- 成員方法:只能訪問靜態成員方法
- 非靜態方法:
- 成員變數:
可以
是靜態的,也可以
是非靜態的 - 成員方法:可以是靜態的成員方法,也可以是非靜態的成員方法。
- 成員變數:
- 靜態方法:
靜態變數和成員變數區別
- 靜態變數也叫類變數,成員變數也叫物件變數。
- 所屬不同
靜態
變數屬於類
成員
變數屬於物件
- 記憶體中的位置不同:
- 靜態變數儲存於
方法區的靜態區
- 成員變數儲存於
堆記憶體
- 靜態變數儲存於
程式碼塊
程式碼塊概述
- Java中,使用
{}括起來的程式碼
稱為程式碼塊
程式碼塊的分類
- 根據位置和宣告的不同,可以分為區域性程式碼塊,構造程式碼塊,靜態程式碼塊和同步程式碼塊
程式碼塊的應用
區域性程式碼塊
- 在
方法中
出現,可以限定變數的生命週期,及早釋放,提高記憶體利用率
。
- 在
構造程式碼塊
(初始化程式碼塊)- 在類中
方法外
出現,將多個構造器中的相同程式碼放到一起,每次呼叫構造器都執行,並且在構造方法前執行
。
- 在類中
靜態程式碼塊
- 在類中
方法外
出現,並且用static
修飾,用於給程式碼塊中的程式碼靜態化,加入靜態域中,在類載入的時候直接執行,並且只執行一次。
- 靜態程式碼塊
優先於main
方法執行。 - 一般常用於
載入驅動
、IO操作
等消耗資源的程式碼
- 在類中
程式碼塊面試題
根據程式寫輸出結果,考察執行順序
class Student {
static {
System.out.println("Student 靜態程式碼塊");
}
{
System.out.println("Student 構造程式碼塊");
}
public Student() {
System.out.println("Student 構造方法");
}
}
class StudentTest {
static {
System.out.println("StudentTest靜態程式碼塊");
}
public static void main(String[] args) {
System.out.println("我是main方法");
Student s1 = new Student();
Student s2 = new Student();
}
}
測試結果:
StudentTest靜態程式碼塊
我是main方法
Student 靜態程式碼塊
Student 構造程式碼塊
Student 構造方法
Student 構造程式碼塊
Student 構造方法
分析:
main方法是Java程式的入口,JVM先找main方法,先把有main方法的類載入到記憶體中,此時StudentTest類的靜態程式碼塊直接隨著類的載入而先執行;
隨後main方法開始執行,當Student類被例項化後,Student類的靜態程式碼塊先執行,並且只執行一個,不管例項化多少物件;
之後,每例項化一次Student類,類中的構造程式碼塊比構造方法就會先執行,並且每例項化一次就執行一次。
初始化執行順序總結
- 當程式執行時,如果需要建立某個類的物件,那麼Java會
先檢查是否載入
了這個類,如果沒有載入,則先執行類的載入再生成物件。如果已經載入,則直接生成物件。 - 類的執行順序過程:
- 首先類先載入到方法區記憶體中,類的靜態域會先被載入並且初始化並且優先於main方法執行。Java中類的載入時按需載入,需要時才載入,並且只加載一次。
- 靜態成員變數和靜態程式碼塊的執行順序同程式碼中的順序一致。
- 每建立一次物件時,先初始化物件中的成員變數,再執行構造程式碼塊,其次再執行構造方法。
- 類中的變數會在任何方法(包括構造器)呼叫之前得到初始化,即使變數散佈於方法定義之間。
- 首先類先載入到方法區記憶體中,類的靜態域會先被載入並且初始化並且優先於main方法執行。Java中類的載入時按需載入,需要時才載入,並且只加載一次。
Java記憶體區域分配
- 此分配圖基於Java8之前版本