這篇文章是關(guān)于Java static關(guān)鍵字的使用,主要會(huì)介紹以下的內(nèi)容:
- static 的概念
- static的各種應(yīng)用
- 總結(jié)
static 是什么
static 顧名思義是靜態(tài)的意思。與this相對(duì),static表示所修飾的部分是屬于類本身所有的,不依賴與某個(gè)具體的實(shí)例。 而this上個(gè)博客已經(jīng)講了,可參考this的使用.this表示的是對(duì)調(diào)用方法的那個(gè)當(dāng)前對(duì)象的引用,可以看做是類的實(shí)例的引用,依賴于具體的實(shí)例。所以這也就是《Java編程思想》里面說的
“static方法就是沒有this的方法。在static方法內(nèi)部不能調(diào)用非靜態(tài)方法,反過來是可以的。而且可以在沒有創(chuàng)建任何對(duì)象的前提下,僅僅通過類本身來調(diào)用static方法。這實(shí)際上正是static方法的主要用途?!?/p>
在了解他使用之前,我們先思考一下,為什么我們需要使用staitc,一切都通過對(duì)象去調(diào)用不也可以嗎?
這樣做是可以,對(duì)象是可以調(diào)用實(shí)例變量,實(shí)例方法,類方法,類成員變量。但是這樣真的好嗎?我們有一些東西是不依賴具體對(duì)象。比如我們有一些工具類,如Math,里面的cos,sin這些都是客觀存在,不會(huì)改變的。任何一個(gè)對(duì)象都不影響Math里面的任何東西,相反,像我們定義一個(gè)圓這個(gè)類,那么圓的半徑,圓的面積顯然是不同的圓 是不同的 這就不能用static。
好了,我們已經(jīng)知道了static是什么,以及該什么時(shí)候去使用它,那我們我們都可以怎么用它呢?
static的用法
- static 變量
- static 方法
- static 代碼塊
static 變量
static變量就是靜態(tài)的成員變量,所謂靜態(tài)變量就是靜態(tài)變量是歸類本身所有,被所有對(duì)象所共享,在內(nèi)存中只有一個(gè)副本。而非靜態(tài)的就是每個(gè)對(duì)象所有,在內(nèi)存中有多個(gè)副本,每個(gè)對(duì)象的副本互不影響。
比如我們常常自己定義或者是看源碼中有很多常量,這些常量就是用final static修飾的。用static來修飾,讓這個(gè)常量不需要new一個(gè)對(duì)象就能得到,非常的方便。例子如下:
/**
* Created by byhieg on 2016/6/20.
*/
public class CityFragment extends Fragment {
public static final String TAG = "CityFragment";
//省略其他代碼
}
這樣,我們就可以直接通過CityFragment.TAG來得到TAG。
static 方法
static 方法和static 變量的使用目的是一致的,一般用來不通過創(chuàng)建對(duì)象來使用方法,用來做工具類的方法。如我們可以把處理字符串的操作的方法統(tǒng)一放到一個(gè)固定類里面,我們調(diào)用的時(shí)候,只需要通過類名.方法名就可以,省去每次創(chuàng)建對(duì)象浪費(fèi)的內(nèi)存。比如下面的例子
/**
* Created by byhieg on 2016/6/20.
*/
public class StringUtils {
//根據(jù)輸入的指定的字符,分割字符串
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();
}
}
我們可以直接這么調(diào)用StringUntils.splitString(args1,args2)
下面,我們說一些用static 方法的注意事項(xiàng)。我們看一下下面的例子。
/**
* 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);
}
}
運(yùn)行會(huì)出現(xiàn)下面的錯(cuò)誤
Error:(13, 28) java: 無(wú)法從靜態(tài)上下文中引用非靜態(tài) 方法 test()
Error:(14, 28) java: 無(wú)法從靜態(tài)上下文中引用非靜態(tài) 變量 error
雖然我們舉例用的Main方法,但他是static方法,使用的是統(tǒng)一的static語(yǔ)法規(guī)則。報(bào)錯(cuò)的原因是因?yàn)樵陟o態(tài)方法中我們是無(wú)法調(diào)用非靜態(tài)的成員變量和方法。因?yàn)榉庆o態(tài)的方法和變量是依賴于對(duì)象創(chuàng)建,對(duì)象才能調(diào)用的。所以是不可以調(diào)用的。但是在非靜態(tài)方法中,是可以調(diào)用全部,因?yàn)樯衔恼f了 靜態(tài)的是歸所有對(duì)象共享,非靜態(tài)是省略了this才調(diào)用成功的。
/**
* 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 實(shí)際應(yīng)該是this.test1(),this.error
//所以也是通過對(duì)象對(duì)調(diào)用的非靜態(tài)的變量和方法
test1();
}
public void test1() {
System.out.println(str);
System.out.println(error);
}
public static void main(String[] args) {
new Main().test();
}
}
static 初始化塊
在說明靜態(tài)初始化塊的時(shí)候,我們先了解一下什么是初始化塊。當(dāng)我們需要生成很多對(duì)象的時(shí)候,每次都需要執(zhí)行構(gòu)造方法,如果我們的構(gòu)造方法中,有一些代碼是不依賴參數(shù)的,我們就可以把這些代碼提取出來,放到同一個(gè)地方。這個(gè)地方我們稱之為初始化塊。
初始化塊允許定義很多個(gè),執(zhí)行順序與書寫的順序有關(guān),但實(shí)際沒什么卵用,因?yàn)樗莿?chuàng)建Java對(duì)象時(shí)隱式執(zhí)行,且全部被執(zhí)行,完全可以把他們放到一起去執(zhí)行。初始化塊的執(zhí)行會(huì)先于構(gòu)造器,這點(diǎn)很重要。
接下來,我們看一下static靜態(tài)塊,static靜態(tài)塊除了有靜態(tài)塊的優(yōu)點(diǎn)以外,他還有static所帶來的優(yōu)點(diǎn),即他在類初次被加載時(shí)執(zhí)行,且只會(huì)執(zhí)行一次。不會(huì)像普通代碼塊一樣,每次對(duì)象創(chuàng)建時(shí)都會(huì)執(zhí)行,這樣我們可以把一些造成空間浪費(fèi)的語(yǔ)句,放到靜態(tài)初始化塊中執(zhí)行。比如下面的代碼
/**
* Created by byhieg on 2016/6/20.
*/
public class Main {
public Main() {
Integer a = new Integer(1024);
//省略其他初始化代碼
}
}
每次在new一個(gè)新對(duì)象的時(shí)候,都會(huì)創(chuàng)建一個(gè)新的Integer對(duì)象。這樣無(wú)疑浪費(fèi)空間,這時(shí)我們就需要用靜態(tài)代碼塊,把Integer a放進(jìn)去,就可以保證只會(huì)初始化一次。如下:
/**
* Created by byhieg on 2016/6/20.
*/
public class Main {
public static Integer a;
static {
a = new Integer(1024);
}
public Main() {
//省略構(gòu)造器其他代碼
}
}
靜態(tài)初始化塊執(zhí)行的順序在普通初始化塊執(zhí)行之前,因?yàn)橹挥蓄惐患虞d并初始化之后,我們才能創(chuàng)建類的的實(shí)例,但以后再創(chuàng)建的實(shí)例的時(shí)候就不會(huì)再執(zhí)行靜態(tài)初始化塊了。
總結(jié)
static 是與類相關(guān)的一個(gè)關(guān)鍵字,所修飾的部分表明該部分是歸類所有。比如static修飾變量就表明該變量是靜態(tài)變量,被所有對(duì)象所共享,被類所擁有。static修飾方法,與變量時(shí)一致的,只是在靜態(tài)方法中是不允許調(diào)用非靜態(tài)的變量和方法。而靜態(tài)代碼塊是比較特殊的存在,用來初始化一些共有的東西,在類被加載時(shí)只執(zhí)行一次。