Ⅰ java中的靜態代碼塊、代碼塊、構造器的執行順序是怎樣呢,這三者有什麼作用呢
還是不得不拿出<clinit>和<init>說事了。以下拿類T作為講解的對象類型吧:
class T{
private static final String msg = "this is a test class!";
private static int version = 1;
static{
version = 2;
desc = "class T";
}
private static String desc = 「T is a test Class」;
private int age = 2;
{
age = 10;
name = "panda";
}
public T(){
age = 12;
name = "foxli";
}
private String name = "micky";
}
類T,存在靜態域version和desc,實例域和name。
類中,存在靜態代碼塊static{}以及實例化代碼塊{}和默認的構造方法。
------------------------------------------------------------------------------------------------------------
先來說一下類型初始化方法<clinit>:
JVM通過Classload進行類型載入時,如果在載入時需要進行類型初始化操作時,則會調用類型的初始化方法。類型初始化方法主要是對static變數進行初始化操作,對static域和static代碼塊初始化的邏輯全部封裝在<clinit>方法中。
java.lang.Class.forName(String name, boolean initialize,ClassLoader loader),其中第二個參數就是是否需要初始化。
Java類型初始化過程中對static變數的初始化操作依賴於static域和static代碼塊的前後關系,static域與static代碼塊聲明的位置關系會導致java編譯器生成<clinit>方法打位元組碼。
由上例子,T類型的類型初始化方法<clinit>最後編譯出來的位元組碼順序大概是這樣的:
T.<clinit>{
private static int version;
private static String desc;
version = 1;
version = 2;
desc = "class T";
desc = "T is a test Class";
}
類型的初始化方法<clinit>只在該類型被載入時才執行,且只執行一次。
-------------------------------------------------------------------------------------------------------------
接下來說一下對象實例化方法<init>:
Java對象在被創建時,會進行實例化操作。該部分操作封裝在<init>方法中,並且子類的<init>方法中會首先對父類<init>方法的調用。
Java對象實例化過程中對實例域的初始化賦值操作全部在<init>方法中進行,<init>方法顯式的調用父類的<init>方法,實例域的聲明以及實例初始化語句塊同樣的位置關系會影響編譯器生成的<init>方法的位元組碼順序,<init>方法以構造方法作為結束。
由上例子,T對象的對象實例化方法<init>最後編譯出來的位元組碼順序大概是這樣的:
T.<init>{
int age;
String name;
this.age = 2;
this.age = 10;
this.name = "panda";
this.name = "micky";
this.age = 12;
this.name = "foxli";
}
對象實例化方法<init>以構造方法作為結束。當前並沒有考慮存在父類的情況,如果存在,<init>方法首先會調用父類的<init>方法。
-------------------------------------------------------------------------------------------------------------
PS:這裡面的msg稱為編譯時常量,他不再<clinit>方法中出現。
其中<clinit>方法在javap命令中沒有顯示,javap輸出的static{}就是<clinit>方法。
Ⅱ Java的靜態塊和初始化塊分別何時執行有什麼區別
靜態初始化塊:當類第一次載入時執行。
非靜態初始化塊:非靜態初始化塊會在構造函數執行時,且在構造函數主體代碼執行之前被執行。
區別如下:
1、執行次數不同
靜態塊只執行一次,初始化塊可以執行多次。
2、作用不同
靜態初始化塊僅能初始化類變數,即static修飾的數據成員。
非靜態初始化塊可以初始化類的實例變數。
(2)java靜態代碼塊調用擴展閱讀:
使用Java靜態代碼塊注意事項:
1、它是隨著類的載入而執行,只執行一次,並優先於主函數。具體說,靜態代碼塊是由類調用的。類調用時,先執行靜態代碼塊,然後才執行主函數的。
2、靜態代碼塊其實就是給類初始化的,而構造代碼塊是給對象初始化的。
3、靜態代碼塊中的變數是局部變數,與普通函數中的局部變數性質沒有區別。
4、一個類中可以有多個靜態代碼塊。
5、對於靜態變數、靜態初始化塊、變數、初始化塊、構造器,它們的初始化順序依次是(靜態變數、靜態初始化塊)>(變數、初始化塊)>構造器。
Ⅲ Java靜態代碼塊和靜態方法的區別
沒有靜態類,如果有什麼需要提前實例化的話,參考下面方式
static
int
i;
static{
i=1;
}
public
static
void
f(){
system.out.println(i);
}
Ⅳ java 調用靜態方法和構造函數和靜態塊執行的先後順序
java中首先是靜態塊先執行,靜態方法,最後是構造函數。示例如下:
publicclassExA{
static{
System.out.println("父類--靜態代碼塊");
}
publicExA(){
System.out.println("父類--構造函數");
}
{
System.out.println("父類--非靜態代碼塊");
}
publicstaticvoidmain(String[]args){
newExB();
}
}
classExBextendsExA{
static{
System.out.println("子類--靜態代碼塊");
}
{
System.out.println("子類--非靜態代碼塊");
}
publicExB(){
System.out.println("子類--構造函數");
}
}
執行結果
=====
父類--靜態代碼塊
子類--靜態代碼塊
父類--非靜態代碼塊
父類--構造函數
子類--非靜態代碼塊
子類--構造函數
Ⅳ java,靜態方法為什麼不能調用類成員
樓主想問的應該是不用調用成員變數吧
首先,這涉及到代碼執行優先順序的問題,在一個Java類中,存在的代碼形式有靜態代碼塊(花括弧{}包裹住的代碼片段),靜態方法,構造函數,成員方法。不同形式的代碼執行順序不同:
1、靜態代碼塊:當類被載入時,靜態代碼塊被執行,且只被執行一次,靜態代碼塊常用來執行類屬性的初始化。
2、靜態方法(也叫類方法):在類載入的時候,在不創建對象的情況下執行,可以直接用類名調用。
兩者的區別是靜態代碼塊是主動執行的,靜態方法是被動執行,只有被調用時才執行。
3、構造函數在創建對象的時候執行。
4、成員方法在被調用的時候執行。
總結:Java代碼執行先後順序:靜態代碼塊>靜態方法>構造函數=非靜態代碼塊。
在了解執行順序後,樓主的問題就很容易解答了。
從層級上看,靜態方法屬於類級別,成員變數屬於對象級別。同時靜態方法也先於構造函數執行,內存也沒給類成員分配空間,說白就是都不存在,你靜態方法調用一個不存在的變數肯定不行的呀。