2017年11月5日 星期日

Day2-9 Static 靜態

1.3 Develop code that declares, initializes, and uses primitives, arrays, enums, and objects as static, instance, and local variables. Also, use legal identifiers for variable names. 

Static variable and Static methods
static使用的時機及理由: 
  1. 總是用同樣的方式執行method: 想像一個情境,當有一個Time的Class內有一個display method,裡面的唯一功能就是印出今天的時間,也就是說不管今天Time的instance狀態為何,都不會改變display method輸出的結果。既然這個method不會和instance的狀態有任何關係,其實也不需要透過instance執行它。那麼其實就可以透過class來執行它!
  2. 紀錄instance個數: 假設今天我們想要知道一個Class有多少個instance個數,這時候不能把這個變數當成instance variable,因為一旦new了一個instance,這個值就會歸0
- 被標示成static的variable或是method是屬於class的,並不是屬於instance的
- 可以不透過instance去存取,僅透過class就能存取static的variable或是method
- instance間共享static class和一份static variable
下面的例子示範static variable
public class Language {
    static int counter;
    public Language(){
        counter++;
    }
    public static void main(String[] args){
        new Language();
        new Language();
        new Language();
        System.out.println(counter);
    }
}
  • static variable不需要初始化,在class被JVM第一次載入的時候就會給初始值了。
  • 不論何時new instance,都會靜態的增加counter的值。而這個程式跑完的結果是"3"
如果將static variable改成instance variable
public class Language {
    int counter;
    public Language(){
        counter++;
    }
    public static void main(String[] args){
        new Language();
        new Language();
        new Language();
        System.out.println(counter);
    }
}
則這段程式會編譯失敗,原因是因為JVM不知道counter是屬於哪個instance的counter,所以沒辦法編譯。且還有一個原因是,main是static method,也代表他是一個不需要instance來執行的method。因為對static method來說,並沒有(也不知道) instance的存在,所以不能直接存取instance variable。這樣的概念也可以用在instance method。static method不能直接使用instance method。static=class等級,not static=instance等級。對static method來說,就是一個不需要任何instance就能夠完成的method。

常見錯誤範例: 在static method裡面對instance variable做存取
public class Display {
    int x = 3;
    public static void main(String[] args){
        System.out.println(x);//Compile error!
    }
}

對static method而言,根本不知道這個存取的instance variable是指哪個instance內的variable。因為static method是class等級來執行的。規則是:一個class的static method,不能存取它自己type的instance variable or method

Access static variable and static methods
要使用static variable,可以使用class+"."+static variable,例如Language.counter
但是,Java也允許以下用法:
public class Language {
    static int counter;
    public Language(){
        counter++;
    }
    public static void main(String[] args){
        Language l = new Language();
        System.out.println(l.counter);
    }
}

也就是可以使用new出來object的reference variable去存取static variable。但在這邊要注意

  • 對JVM來說,他看到的其實是Language.counter,就算寫的是l.counter(也就是class等級)。
  • 雖然使用reference variable對static variable做存取,但是static members還是不知道是誰對他們做了存取,只知道是type是Language。換句話說,compiler只關心type是誰。
注意!static method是不能被override,就算真的在subclass寫了一個一樣的static method,那也只是從新定義一個新的static method而已,並不是override。如下範例:
class Animal{
    static void display(){
        System.out.println("Use Animal static method");
    }
}
class Cat extends Animal{
    static void display(){
        System.out.println("Use Cat static method");
    }

}
class testOverrideStatic {
    public static void main(String[] args){
        Animal[] animalArray = {new Animal(), new Cat(), new Animal()};
        for(Animal a:animalArray){
            a.display();
        }
    }
}
結果如下:
Use Animal static method
Use Animal static method
Use Animal static method
這也表示,

  • 此行a.display()對compiler來說會自動轉成Animal.display()
  • 就算有Cat()的物件在執行a.display(),對編譯器來說只參考reference variable的type是誰(此處皆是Animal)
Static method不能被override的原因:
想想為什麼要override,原因是透過polymorphism來實現該實體透過override去執行真正需要做的事情。既然static不在class層,不需要instance就能夠執行,代表也不需要有override的行為(因為沒辦法使用instance透過polymorphism找出真正被實作的method)
另外static method的好處:不需要等到runtime的時候才決定要做的真實method是哪一個,可以加快速度。

沒有留言:

張貼留言