java static 的理解
首先,先回顧static在C++中的作用:
static的作用主要有兩種:
第一個作用是限定作用域;第二個作用是保持變數內容持久化;
1、全域性靜態變數:
用法:在全域性變數前加上關鍵字static,全域性變數就定義成一個全域性靜態變數。 static int temp;
記憶體中的位置:靜態儲存區,在整個程式執行期間一直存在。
初始化:未經初始化的全域性靜態變數會被自動初始化為0(自動物件的值是任意的,除非他被顯式初始化);
作用域:全域性靜態變數在宣告他的檔案之外是不可見的,準確地說是從定義之處開始,到檔案結尾。
2、區域性靜態變數:
在區域性變數之前加上關鍵字static,區域性變數就成為一個區域性靜態變數。
記憶體中的位置:靜態儲存區
初始化:未經初始化的全域性靜態變數會被自動初始化為0(自動物件的值是任意的,除非他被顯式初始化);
作用域:作用域仍為區域性作用域,當定義它的函式或者語句塊結束的時候,作用域結束。但是當局部靜態變數離開作用域後,並沒有銷燬,而是仍然駐留在記憶體當中,只不過我們不能再對它進行訪問,直到該函式再次被呼叫,並且值不變;
3、靜態函式:
在函式返回型別前加關鍵字static,函式就定義成靜態函式。函式的定義和生命在預設情況下都是extern的,但靜態函式只是在宣告他的檔案當中可見,不能被其他檔案所用;
類的靜態函式是該類的範疇內的全域性函式,不能訪問類的私有成員,只能訪問類的靜態成員,不需要類的例項即可呼叫;實際上,他就是增加了類的訪問許可權的全域性函式;
java static
在《Java程式設計思想》P86頁有這樣一段話:
“static方法就是沒有this的方法。在static方法內部不能呼叫非靜態方法,反過來是可以的。而且可以在沒有建立任何物件的前提下,僅僅通過類本身來呼叫static方法。這實際上正是static方法的主要用途。”
總而言之java中static的作用:方便在沒有建立物件的情況下來進行呼叫(方法/變數)。
很顯然,被static關鍵字修飾的方法或者變數不需要依賴於物件來進行訪問,只要類被載入了,就可以通過類名去進行訪問。
static方法一般稱作靜態方法,由於靜態方法不依賴於任何物件就可以進行訪問,因此對於靜態方法來說,是沒有this的,因為它不依附於任何物件,既然都沒有物件,就談不上this了。並且由於這個特性,在靜態方法中不能訪問類的非靜態成員變數和非靜態成員方法,因為非靜態成員方法/變數都是必須依賴具體的物件才能夠被呼叫。
因此,如果說想在不建立物件的情況下呼叫某個方法,就可以將這個方法設定為static。我們最常見的static方法就是main方法,至於為什麼main方法必須是static的,現在就很清楚了。因為程式在執行main方法的時候沒有建立任何物件,因此只有通過類名來訪問。
static變數也稱作靜態變數,靜態變數和非靜態變數的區別是:靜態變數被所有的物件所共享,在記憶體中只有一個副本,它當且僅當在類初次載入時會被初始化。而非靜態變數是物件所擁有的,在建立物件的時候被初始化,存在多個副本,各個物件擁有的副本互不影響。
static成員變數的初始化順序按照定義的順序進行初始化。
static是不允許用來修飾區域性變數。不要問為什麼,這是Java語法的規定。
static{}(即static塊),會在類被載入的時候執行且僅會被執行一次,一般用來初始化靜態變數和呼叫靜態方法。
程式碼分析:(分析下面的程式碼的輸出結果)
package fistJava;
import java.util.*;
public class Game extends Base{
static{
System.out.println("test static");
}
public Game(){
System.out.println("test constructor");
}
public static void main(String[] args) {
new Game();
}
}
class Base{
static{
System.out.println("base static");
}
public Base(){
System.out.println("base constructor");
}
}
首先找到main()函式的入口,進入之前需要載入Game類,載入的時候發現,Game類繼承了Base類,所以,先去載入Base類,載入時發現有static,便執行了static塊,接著又去載入Game類,同樣發現有static塊,就先執行,最後類載入完以後,執行main函式,new一個類的時候,先呼叫父類構造器,最後呼叫自己的構造器。