這篇文章是關於Java static關鍵字的使用,主要會介紹以下的內容: 1. static 的概念 2. static的各種應用 3. 總結 static 是什麼 static 顧名思義是靜態的意思。與this相對,static表示所修飾的部分是屬於類本身所有的,不依賴與某個具體的實例。 而thi ...
這篇文章是關於Java static關鍵字的使用,主要會介紹以下的內容:
- static 的概念
- static的各種應用
- 總結
static 是什麼
static 顧名思義是靜態的意思。與this相對,static表示所修飾的部分是屬於類本身所有的,不依賴與某個具體的實例。 而this上個博客已經講了,可參考this的使用.this表示的是對調用方法的那個當前對象的引用,可以看做是類的實例的引用,依賴於具體的實例。所以這也就是《Java編程思想》裡面說的
“static方法就是沒有this的方法。在static方法內部不能調用非靜態方法,反過來是可以的。而且可以在沒有創建任何對象的前提下,僅僅通過類本身來調用static方法。這實際上正是static方法的主要用途。”
在瞭解他使用之前,我們先思考一下,為什麼我們需要使用staitc,一切都通過對象去調用不也可以嗎?
這樣做是可以,對象是可以調用實例變數,實例方法,類方法,類成員變數。但是這樣真的好嗎?我們有一些東西是不依賴具體對象。比如我們有一些工具類,如Math
,裡面的cos,sin
這些都是客觀存在,不會改變的。任何一個對象都不影響Math裡面的任何東西,相反,像我們定義一個圓這個類,那麼圓的半徑,圓的面積顯然是不同的圓 是不同的 這就不能用static。
好了,我們已經知道了static是什麼,以及該什麼時候去使用它,那我們我們都可以怎麼用它呢?
static的用法
- static 變數
- static 方法
- static 代碼塊
static 變數
static變數就是靜態的成員變數,所謂靜態變數就是靜態變數是歸類本身所有,被所有對象所共用,在記憶體中只有一個副本。而非靜態的就是每個對象所有,在記憶體中有多個副本,每個對象的副本互不影響。
比如我們常常自己定義或者是看源碼中有很多常量,這些常量就是用final static修飾的。用static來修飾,讓這個常量不需要new一個對象就能得到,非常的方便。例子如下:
/**
* Created by byhieg on 2016/6/20.
*/
public class CityFragment extends Fragment {
public static final String TAG = "CityFragment";
//省略其他代碼
}
這樣,我們就可以直接通過CityFragment.TAG
來得到TAG。
static 方法
static 方法和static 變數的使用目的是一致的,一般用來不通過創建對象來使用方法,用來做工具類的方法。如我們可以把處理字元串的操作的方法統一放到一個固定類裡面,我們調用的時候,只需要通過類名.方法名
就可以,省去每次創建對象浪費的記憶體。比如下麵的例子
/**
* Created by byhieg on 2016/6/20.
*/
public class StringUtils {
//根據輸入的指定的字元,分割字元串
public static String[] splitString(String str,String regex) {
String [] result = str.split(regex);
return result;
}
//刪除指定位置的字元串
public static String delPosOfString(String str, int[] pos) {
StringBuffer sb = new StringBuffer(str);
for(int i = 0 ; i < pos.length;i++) {
sb.deleteCharAt(pos[i]);
}
return sb.toString();
}
}
我們可以直接這麼調用StringUntils.splitString(args1,args2)
下麵,我們說一些用static 方法的註意事項。我們看一下下麵的例子。
/**
* Created by byhieg on 2016/6/20.
*/
public class Main {
public static final String str = "byhieg";
public String error = "error";
public void test() {
System.out.println(str);
System.out.println(error);
}
public static void main(String[] args) {
System.out.println(test());
System.out.println(error);
System.out.println(str);
}
}
運行會出現下麵的錯誤
Error:(13, 28) java: 無法從靜態上下文中引用非靜態 方法 test()
Error:(14, 28) java: 無法從靜態上下文中引用非靜態 變數 error
雖然我們舉例用的Main方法,但他是static方法,使用的是統一的static語法規則。報錯的原因是因為在靜態方法中我們是無法調用非靜態的成員變數和方法。因為非靜態的方法和變數是依賴於對象創建,對象才能調用的。所以是不可以調用的。但是在非靜態方法中,是可以調用全部,因為上文說了 靜態的是歸所有對象共用,非靜態是省略了this才調用成功的。
/**
* Created by byhieg on 2016/6/20.
*/
public class Main {
public static final String str = "byhieg";
public String error = "error";
public void test() {
System.out.println(str);
System.out.println(error);
//此處省略了this 實際應該是this.test1(),this.error
//所以也是通過對象對調用的非靜態的變數和方法
test1();
}
public void test1() {
System.out.println(str);
System.out.println(error);
}
public static void main(String[] args) {
new Main().test();
}
}
static 初始化塊
在說明靜態初始化塊的時候,我們先瞭解一下什麼是初始化塊。當我們需要生成很多對象的時候,每次都需要執行構造方法,如果我們的構造方法中,有一些代碼是不依賴參數的,我們就可以把這些代碼提取出來,放到同一個地方。這個地方我們稱之為初始化塊。
初始化塊允許定義很多個,執行順序與書寫的順序有關,但實際沒什麼卵用,因為他是創建Java對象時隱式執行,且全部被執行,完全可以把他們放到一起去執行。初始化塊的執行會先於構造器,這點很重要。
接下來,我們看一下static靜態塊,static靜態塊除了有靜態塊的優點以外,他還有static所帶來的優點,即他在類初次被載入時執行,且只會執行一次。不會像普通代碼塊一樣,每次對象創建時都會執行,這樣我們可以把一些造成空間浪費的語句,放到靜態初始化塊中執行。比如下麵的代碼
/**
* Created by byhieg on 2016/6/20.
*/
public class Main {
public Main() {
Integer a = new Integer(1024);
//省略其他初始化代碼
}
}
每次在new一個新對象的時候,都會創建一個新的Integer對象。這樣無疑浪費空間,這時我們就需要用靜態代碼塊,把Integer a放進去,就可以保證只會初始化一次。如下:
/**
* Created by byhieg on 2016/6/20.
*/
public class Main {
public static Integer a;
static {
a = new Integer(1024);
}
public Main() {
//省略構造器其他代碼
}
}
靜態初始化塊執行的順序在普通初始化塊執行之前,因為只有類被載入並初始化之後,我們才能創建類的的實例,但以後再創建的實例的時候就不會再執行靜態初始化塊了。
總結
static 是與類相關的一個關鍵字,所修飾的部分表明該部分是歸類所有。比如static修飾變數就表明該變數是靜態變數,被所有對象所共用,被類所擁有。static修飾方法,與變數時一致的,只是在靜態方法中是不允許調用非靜態的變數和方法。而靜態代碼塊是比較特殊的存在,用來初始化一些共有的東西,在類被載入時只執行一次。