Java基礎-static關鍵字和單例模式

static關鍵字

  • static關鍵字的特色java

    1. 用來修飾類的成員-修飾成員變量的稱之爲類變量(靜態變量),修飾成員方法的稱之爲類方法(靜態方法)。(屬性拿static修飾完以後就不叫屬性了,他也就不屬於任何對象了,而是屬於多個對象共享的,就叫類變量或靜態變量,方法也同樣)bash

    2. 當類被加載的時候就會被加載,優先於對象的存在。ui

    3. 用來修飾與語句塊-稱之爲靜態代碼塊。先於構造方法以前執行,只會執行一次。用來對靜態成員作初始化this

    4. 靜態修飾的成員被全部的對象共享spa

    5. 調用的時候能夠直接經過類名.成員來進行訪問。code

  • 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,音視頻方向的文章,歡迎你們關注,共同進步。

相關文章
相關標籤/搜索