java的static代碼塊的理解

先來看一個例子:

class Parent{ 
static String name = "hello"; 

System.out.println("parent block"); 

static { 
System.out.println("parent static block"); 

public Parent(){ 
System.out.println("parent constructor"); 




class Child extends Parent{ 
static String childName = "hello"; 

System.out.println("child block"); 

static { 
System.out.println("child static block"); 

public Child(){ 
System.out.println("child constructor"); 

}


public class Value {
public static void main(String[] args) { 
new Child();//語句(*)  
}
}

輸出結果就是:

parent static block
child static block
parent block
parent constructor
child block
child constructor



分析:當執行new Child()時,它首先去看父類裏面有沒有靜態代碼塊,如果有,它先去執行父類裏面靜態代碼塊裏面的內容,當父類的靜態代碼塊裏面的內容執行完畢之後,接着去執行子類(自己這個類)裏面的靜態代碼塊,當子類的靜態代碼塊執行完畢之後,它接着又去看父類有沒有非靜態代碼塊,如果有就執行父類的非靜態代碼塊,父類的非靜態代碼塊執行完畢,接着執行父類的構造方法;父類的構造方法執行完畢之後,它接着去看子類有沒有非靜態代碼塊,如果有就執行子類的非靜態代碼塊。子類的非靜態代碼塊執行完畢再去執行子類的構造方法,這個就是一個對象的初始化順序。

java 靜態代碼塊 靜態方法區別
一般情況下,如果有些代碼必須在項目啓動的時候就執行的時候,需要使用靜態代碼塊,這種代碼是主動執行的;需要在項目啓動的時候就初始化,在不創建對象的情況下,其他程序來調用的時候,需要使用靜態方法,這種代碼是被動執行的. 靜態方法在類加載的時候 就已經加載 可以用類名直接調用
比如main方法就必須是靜態的 這是程序入口
兩者的區別就是:靜態代碼塊是自動執行的;
靜態方法是被調用的時候才執行的.

靜態方法
(1)在Java裏,可以定義一個不需要創建對象的方法,這種方法就是靜態方法。要實現這樣的效果,只需要在類中定義的方法前加上static關鍵字。例如:

public static int maximum(int n1,int n2)

使用類的靜態方法時,注意:

a在靜態方法裏只能直接調用同類中其他的靜態成員(包括變量和方法),而不能直接訪問類中的非靜態成員。這是因爲,對於非靜態的方法和變量,需要先創建類的實例對象後纔可使用,而靜態方法在使用前不用創建任何對象。

b 靜態方法不能以任何方式引用this和super關鍵字,因爲靜態方法在使用前不用創建任何實例對象,當靜態方法調用時,this所引用的對象根本沒有產生。

(2)靜態變量是屬於整個類的變量而不是屬於某個對象的。注意不能把任何方法體內的變量聲明爲靜態,例如:
fun()
{
static int i=0;//非法。
}

(3)一個類可以使用不包含在任何方法體中的靜態代碼塊,當類被載入時,靜態代碼塊被執行,且只被執行一次,靜態塊常用來執行類屬性的初始化。例如:
static
{
}


總結:
對象的初始化順序:首先執行父類靜態的內容,父類靜態的內容執行完畢後,接着去執行子類的靜態的內容,當子類的靜態內容執行完畢之後,再去看父類有沒有非靜態代碼塊,如果有就執行父類的非靜態代碼塊,父類的非靜態代碼塊執行完畢,接着執行父類的構造方法;父類的構造方法執行完畢之後,它接着去看子類有沒有非靜態代碼塊,如果有就執行子類的非靜態代碼塊。子類的非靜態代碼塊執行完畢再去執行子類的構造方法。總之一句話,靜態代碼塊內容先執行,接着執行父類非靜態代碼塊和構造方法,然後執行子類非靜態代碼塊和構造方法


下邊再來看下代碼:

package Test1;


public class Value {
static int value=0;
static {
System.out.println("執行的是類裏邊的代碼塊語句");
value++;
}
}





package Test1;


public class Main_class {
public static void main(String []args){
System.out.println("在裝載類之前執行的語句");
int a=Value.value;
System.out.println("裝載完類執行的語句");
Value v=new Value();
System.out.println(a);
System.out.println(Value.value);
}
}

這個輸出結果就是:

在裝載類之前執行的語句
執行的是類裏邊的代碼塊語句
裝載完類執行的語句
1
1

就是代表任何的類裏邊的static代碼塊的執行時間是在第一次出現類名之前,的那個時刻就執行了,也就是在裝載這個類的時候,記住,裝載類的時候並不代表給那個類實例化,只是給這個類裏邊的靜態數據分配空間的。分配完空間之後就是執行那些靜態數據代碼塊。

當然那些非靜態代碼塊是在實例化一個類的對象的時候執行的。

可以啊看下這個代碼:

package Test1;


public class Value {
static int value=0;
{
System.out.println("執行類中的非靜態代碼塊");
}
static {
System.out.println("執行的是類裏邊的代碼塊語句");
value++;
}
}

package Test1;


public class Main_class {
public static void main(String []args){
System.out.println("在裝載類之前執行的語句");
int a=Value.value;
System.out.println("裝載完類執行的語句");
Value v=new Value();
System.out.println(a);
System.out.println(Value.value);
}
}

在裝載類之前執行的語句
執行的是類裏邊的代碼塊語句
裝載完類執行的語句
執行類中的非靜態代碼塊
1
1


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章