Java常見關鍵字------static

一.static關鍵字的用途

    在《Java編程思想》有這樣一句話“
    “static方法就是沒有this的方法。在static方法內部不能調用非靜態方法,反過來是可以的。而且可以在沒有創建任何對象的前提下,僅僅通過類本身來調用static方法。這實際上正是static方法的主要用途。”
    這段話雖然只是說明了static方法的特殊之處,但是可以看出static關鍵字的基本作用,簡而言之,一句話來描述就是:
    方便在沒有創建對象的情況下來進行調用(方法/變量)。
    很顯然,被static關鍵字修飾的方法或者變量不需要依賴於對象來進行訪問,只要類被加載了,就可以通過類名去進行訪問。
    static可以用來修飾類的成員方法、類的成員變量,另外可以編寫static代碼塊來優化程序性能。
1)static方法

    static方法一般稱作靜態方法,由於靜態方法不依賴於任何對象就可以進行訪問,因此對於靜態方法來說,是沒有this的,因爲它不依附於任何對象,既然都沒有對象,就談不上this了。並且由於這個特性,在靜態方法中不能訪問類的非靜態成員變量和非靜態成員方法,因爲非靜態成員方法/變量都是必須依賴具體的對象才能夠被調用。
    但是要注意的是,雖然在靜態方法中不能訪問非靜態成員方法和非靜態成員變量,但是在非靜態成員方法中是可以訪問靜態成員方法/變量的。舉個簡單的例子:

class MyObject{
	private static String str1 = "staticProperty";
	private String str2 = "property";
	
	public MyObject(){
		
	}
	
	public void print1(){
		System.out.println(str1);
		System.out.println(str2);
		print2();
	}
	
	public void print2(){
		System.out.println(str1);
		System.out.println(str2);
		print1();
	}
}

    在上面的代碼中,由於print2方法是獨立於對象存在的,可以直接用過類名調用。假如說可以在靜態方法中訪問非靜態方法/變量的話,那麼如果在main方法中有下面一條語句:
MyObject.print2();
    此時對象都沒有,str2根本就不存在,所以就會產生矛盾了。同樣對於方法也是一樣,由於你無法預知在print1方法中是否訪問了非靜態成員變量,所以也禁止在靜態成員方法中訪問非靜態成員方法。
    而對於非靜態成員方法,它訪問靜態成員方法/變量顯然是毫無限制的。
    因此,如果說想在不創建對象的情況下調用某個方法,就可以將這個方法設置爲static。我們最常見的static方法就是main方法,至於爲什麼main方法必須是static的,現在就很清楚了。因爲程序在執行main方法的時候沒有創建任何對象,因此只有通過類名來訪問。
另外記住:即使沒有顯示地使用static關鍵字,構造器實際上也是靜態方法
2)static變量
    static變量也稱作靜態變量,靜態變量和非靜態變量的區別是:靜態變量被所有的對象所共享,在內存中只有一個副本,它當且僅當在類初次加載時會被初始化。而非靜態變量是對象所擁有的,在創建對象的時候被初始化,存在多個副本,各個對象擁有的副本互不影響。
    static成員變量的初始化順序按照定義的順序進行初始化。
3)static代碼塊
    static關鍵字還有一個比較關鍵的作用就是 用來形成靜態代碼塊以優化程序性能。static塊可以置於類中的任何地方,類中可以有多個static塊。在類初次被加載的時候,會按照static塊的順序來執行每個static塊,並且只會執行一次。
    爲什麼說static塊可以用來優化程序性能,是因爲它的特性:只會在類加載的時候執行一次。下面看個例子:

class Person{
    private Date birthDate;
     
    public Person(Date birthDate) {
        this.birthDate = birthDate;
    }
     
    boolean isBornBoomer() {
        Date startDate = Date.valueOf("1946");
        Date endDate = Date.valueOf("1964");
        return birthDate.compareTo(startDate)>=0 && birthDate.compareTo(endDate) < 0;
    }
}

    isBornBoomer是用來這個人是否是1946-1964年出生的,而每次isBornBoomer被調用的時候,都會生成startDate和birthDate兩個對象,造成了空間浪費,如果改成這樣效率會更好:

class Person{
    private Date birthDate;
    private static Date startDate,endDate;
    static{
        startDate = Date.valueOf("1946");
        endDate = Date.valueOf("1964");
    }
     
    public Person(Date birthDate) {
        this.birthDate = birthDate;
    }
     
    boolean isBornBoomer() {
        return birthDate.compareTo(startDate)>=0 && birthDate.compareTo(endDate) < 0;
    }
}

因此,很多時候會將一些只需要進行一次的初始化操作都放在static代碼塊中進行。

二.static關鍵字的誤區

1.static關鍵字會改變類中成員的訪問權限嗎?

    有些初學的朋友會將java中的static與C/C++中的static關鍵字的功能混淆了。在這裏只需要記住一點:與C/C++中的static不同,Java中的static關鍵字不會影響到變量或者方法的作用域。在Java中能夠影響到訪問權限的只有private、public、protected(包括包訪問權限)這幾個關鍵字。看下面的例子就明白了:
在這裏插入圖片描述
    提示錯誤"Person.age 不可視",這說明static關鍵字並不會改變變量和方法的訪問權限。

2.能通過this訪問靜態成員變量嗎?

    雖然對於靜態方法來說沒有this,那麼在非靜態方法中能夠通過this訪問靜態成員變量嗎?先看下面的一個例子,這段代碼輸出的結果是什麼?

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