關于Java程序代碼執行的時刻詳細,可以參考Java面試相關(一)-- Java類加載全過程。
示例代碼如下:
public class Test {
//靜態成員
private static int A;
//成員塊
{
System.out.println("成員塊1");
}
//靜態成員塊
static{
System.out.println("靜態代碼塊");
A = 2;
}
//成員對象point
private Point point = new Point();
/**
* 構造方法
*/
public Test(){
System.out.println("Test的構造方法");
}
{
System.out.println("成員塊2");
}
public static class Point{
public Point(){
System.out.println("Point的構造方法");
}
}
public static void main(String[] args){
Test test = new Test();
}
}
運行結果:
靜態代碼塊
成員塊1
Point的構造方法
成員塊2
Test的構造方法
解析:
?當程序在找到main方法入口并準備執行前,Test類本身需要進行編譯、加載和初始化 這三個過程:
- 編譯:如果Test.class沒有生成或者代碼更新了,就會重新將.java文件編譯成.class文件,準備加載。
- 加載:加載這個過程要細分的話,包含:驗證、準備、解析、對主動引用類的情況做處理,這幾個過程,詳細可以看本文前言的文章鏈接。可以理解為:加載過程主要是保證編譯好的.class文件的數據順利被JVM理解并可控。
- 初始化:首先就將Test類整體掃描一遍,并將所有靜態成員附上初始值和靜態代碼塊都執行一遍【所以,類靜態代碼,也稱為初始化塊,在初始化使被執行】,之后,再通過這個入口方法,執行main方法中的代碼。
- 執行main方法,
new Test()
構建一個新的Test類對象,所以,所有的類成員方法塊(包括成員變量的賦值),都會按照代碼先后順序執行。在這些成員代碼塊執行完成后,才會調用類的構造方法。 -
Point point = new Point();
就是因為new Test()
而執行成員代碼塊所以觸發的,于是這里Point類也有一個初始化和構建的過程。