static關鍵字
-
static關鍵字的特點
-
用來修飾類的成員-修飾成員變數的稱之為類變數(靜態變數),修飾成員方法的稱之為類方法(靜態方法)。(屬性拿static修飾完之後就不叫屬性了,他也就不屬於任何物件了,而是屬於多個物件共享的,就叫類變數或靜態變數,方法也一樣)
-
當類被載入的時候就會被載入,優先於物件的存在。
-
用來修飾與語句塊-稱之為靜態程式碼塊。先於構造方法之前執行,只會執行一次。用來對靜態成員做初始化
-
靜態修飾的成員被所有的物件共享
-
呼叫的時候可以直接通過類名.成員來進行訪問。
-
-
static關鍵字注意事項
1.靜態方法中只能訪問外部的靜態成員 (為什麼?當我們去呼叫靜態方法的時候,物件都沒產生,物件沒產生怎麼可能有屬性呢,因為屬性是屬於某個物件的對吧) 2.靜態方法中不能出現this關鍵字 (為什麼?同樣的道理,當我們去呼叫靜態方法的時候,物件都沒產生,物件沒產生this又是指誰呢?)
ok 上程式碼!
public class StaticDemo {
public static void main(String[] args)
{
Device device1 = new Device();
device1.showName();
device1.showEnergy();
Device device2 = new Device();
device2.energy++;
device2.showName();
device2.showEnergy();
}
}
class Device
{
private String name="device1";//普通的屬性
public int energy=2;//普通的屬性
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getEnergy() {
return energy;
}
public void setEnergy(int energy) {
this.energy = energy;
}
public void showName()
{
System.out.println(name);
}
public void showEnergy()
{
System.out.println(energy);
}
}
複製程式碼
看下輸出結果:
device1
2
device1
3
複製程式碼
ok,現在分析下,我第一個物件的energy
屬性初始值時2
,第二個物件的energy
屬性我用public
修飾了,所以我直接可以呼叫下,然後加一
了,列印出來的結果兩個物件是不一樣的。這就說明了什麼?每個物件都有他自己的獨立的一份屬性。對不對?~對的哈。。這句話很重要~~
那我現在如果把name
這個屬性改成用static
來修飾的話,現在會怎麼樣?
public static String name="device1";//靜態變數,他現在不屬於任何一個物件了,被多個物件共享,他現在是屬於類的,他也稱為類變數
現在我們把呼叫方法改成這樣
public static void main(String[] args)
{
Device device1 = new Device();
device1.name = "cyy";
device1.showName();
device1.showEnergy();
Device device2 = new Device();
device2.energy++;
device2.showName();
device2.showEnergy();
}
複製程式碼
現在name
不是個屬性了,他現在是個靜態變數,我在device1
裡面把他設定成cyy
,現在列印結果來看下。
cyy
2
cyy
3
複製程式碼
看到沒兩個name
都變成cyy
了。這說明了什麼?這是不是說明了,這個name
大家都共享了呀,不再是每個物件獨立擁有的了,對吧!
那既然他都不是共享的了,那我們訪問的時候是不是就可以直接Device.name
就可以了啊,因為他現在不屬於物件了,他現在屬於類的。
而age
可不可以直接通過Device.age
來訪問啊,當然不可以,因為他現在並不屬於類對吧。
好的,現在如果我們把一個方法改成靜態的呢,比如這樣:
public static void showName()
{
System.out.println(energy);
System.out.println(name);
}
複製程式碼
如果這麼寫的話,是不是會報錯呀,編譯時就會報錯,會提示:
Non-static field 'energy' cannot be referenced from a static context
什麼意思?大概意思就是說,你靜態方法不能訪問非靜態變數~為什麼?!因為你靜態方法呼叫的時候,還沒有建立物件呢,人家energy
是個屬性,又不是靜態變數,你會跑的時候,人家還沒出生呢,你咋能去找人家玩兒呢?對吧,所以靜態方法不能訪問非靜態變數
,靜態方法中不能使用this
,只能訪問外部靜態的東西。
那非靜態方法
可不可以訪問靜態變數
?思考一下?答案當然是可以的,想像一下,靜態變數在你物件建立之前就已經分配好記憶體空間了,已經存在了,你物件建立完之後,他已經存在了,所以肯定是可以訪問的,對吧。總結就是靜態的只能訪問靜態的,非靜態的都可以訪問
。
還有個static語句塊
他什麼時候執行呢?
在類被載入的時候就會執行,只會執行一次,用來對靜態變數進行初始化。優先於構造方法
的執行。
上程式碼:
class Device
{
public static String name;//普通的屬性
public int energy=2;//普通的屬性
//static語句塊
static {
name = "device1";
System.out.println("===我是靜態語句塊裡的"+name);
}
//構造方法
public Device(String name)
{
this.name = name;
System.out.println("===我是構造方法裡的"+name);
}
public static void showName()
{
System.out.println(name);
}
public void showEnergy()
{
System.out.println(energy);
}
}
複製程式碼
我們現在使用下:
Device device1 = new Device("cyy");
Device device2 = new Device("cyy513");
複製程式碼
看下列印結果:
===我是靜態語句塊裡的device1
===我是構造方法裡的cyy
===我是構造方法裡的cyy513
複製程式碼
發現了吧,我new
了兩個物件,但是靜態語句塊裡的system.out.println
只列印了一次,說明啥static語句塊只執行一次,不管你建立多少次物件。
而且我是先於構造方法執行的。
那會有人說,那我以後都不用屬性了,我全部用static變數,多好,多方便,其實這樣有很多缺點:
- 破壞了java物件導向的封裝性
- static變數的生命週期比較長,程式結束的時候,他的記憶體才會釋放,而屬性呢,這個物件執行完了他的屬性記憶體是不是就釋放了呀。
那我們什麼時候用static呀?
當我們一個類裡面,沒有任何屬性,只有方法 ,而這個方法是為其他的類服務的,這個時候適合用static的。
單例模式
定義:
顧名思義,單例模式的意思就是隻有一個例項,單例模式確保某一個類只有一個例項,而且自行例項化併為整個系統提供這個例項,這個類稱為單例類。
通俗的說,就是我有一個類,整個系統就一個例項,而且他是自己建立自己,他必須對外提供個方法,把我自己給你。
上程式碼:
class SingleTon
{
private SingleTon singleTon = new SingleTon();
/**
* 構造方法一定不能是公開的,不然別人就可以隨便構造了。
* 所以構造方法必須是private,對吧
*/
private SingleTon()
{
}
//如果我這麼寫,會出現什麼問題
public static SingleTon getInstance()
{
return singleTon;
}
}
複製程式碼
是不是會出現之前說的那種錯誤呀,靜態方法不能引用非靜態變數
。對不對。所以要怎麼做?是不是給前面singleton
加上個static
就可以了是吧。因為這個SingleTon是靜態的在記憶體裡只有一份對吧~正確寫法,
class SingleTon
{
public static SingleTon singleTon = new SingleTon();
private SingleTon()
{}
public static SingleTon getInstance()
{
return singleTon;
}
}
複製程式碼
這種方式稱之為餓漢式
。為什麼?因為我在呼叫getInstance()
之前這個物件是不是就已經產生了呀,因為它是靜態的嘛,在類載入時候,就已經new SingleTon()
了呀。那我們現在有沒有更好的方法呢?
比如在getInstance()
的時候再去建立這個物件呀?當然可以呀~這麼寫就可以了.
class SingleTon
{
public static SingleTon singleTon = null;
/**
* 構造方法一定不能是公開的,不然別人就可以隨便構造了。
* 所以構造方法必須是private,對吧
*/
private SingleTon()
{
}
//如果我這麼寫,會出現什麼問題
public static SingleTon getInstance()
{
if (singleTon==null)
{
singleTon = new SingleTon();
}
return singleTon;
}
}
複製程式碼
這種就是懶漢式
載入。
不管是懶漢式
還是餓漢式
,是不是目的就是一個,讓他整個系統中只有一個例項。
ok,結束~ 後續我會繼續更新,Android自定義View,Android NDK,音視訊方向的文章,歡迎大家關注,共同進步。