關鍵字static
一般而言,當你設計某個class 時,其實就是在描述其物件的外觀長相及行
為舉措。除非以new 來產生物件,否則並不存在任何實質的物件。產生物
件之際,儲存空間才會配置出來,其函式才可供外界使用。
但是有兩種情況,是上述方式所無法解決的。第一種是,你希望不論產生
了多少個物件,或不存在任何物件的情形下,那些特定資料的儲存空間都
只有一份。第二種情況是,你希望某個函式不要和class object 綁在一起。
透過關鍵字static,便可以處理這兩種情況。當你將某筆資料成員或某個
函式宣告為static,它就不再被侷限於所屬的class object 上。所以,即使
沒有產生任何class object,外界還是可以呼叫其static 函式,或是取用其
static data。一般情形下,你得產生某個物件,再透過該物件取用其資料
和函式。所以,non-static 資料/函式必須知道它們隸屬於哪一個物件,才
有辦法運作。由於使用static 函式前並不需要先產生任何物件,所以在
static 函式中不能「直接」取用non-static 資料/函式。如果只是單純地
直接呼叫non-static 函式,而沒有指定某個物件,是行不通的,原因是
non-static 資料/函式總是得和特定的物件綑綁在一起。
118 Thinking in Java www.BruceEckel.com
某些物件導向程式語言,以class data 和class methods 兩個詞彙,代表那
些不和特定物件有所關聯,「其存在只是為了class」的資料和函式。有時
候Java 相關文獻也會使用這兩個詞彙。
只要將關鍵字static 擺在資料成員或函式的定義前,就可以使它們成為靜
態。以下便可以產生一筆static 資料成員,並將它初始化:
class StaticTest {
static int i = 47;
}
現在,即使你產生兩個StaticTest 物件,StaticTest.i 仍然只有一份。產
生出來的那兩個物件會共用同一個i。再看這個:
StaticTest st1 = new StaticTest();
StaticTest st2 = new StaticTest();
此時st1.i 和st2.i 的值一樣,都是47,因為它們都指向同一塊記憶體。
有兩種方法可以取用宣告為static 的變數。一如上例,你可以透過某個物
件來定址,例如st2.i。也可以直接經由其class 名稱完成參考動作— 這種
作法對non-static 成員是行不通的(但對於static 成員卻比較好,因為這
種寫法可以更強調所參考的對象是個static 成員)。
StaticTest.i++;
++運算子會將變數值累加1。經過這個動作,st1.i 和st2.i 的值都是48。
相同的模式可以推廣到static 函式。你可以透過物件來取用某個static 函
式,和取用其他普通的函式沒什麼兩樣。你也可以經由以下特殊語法取用
之:ClassName.method()。定義static 函式的方式和定義static data
member 的方式十分類似:
class StaticFun {
static void incr() { StaticTest.i++; }
}
你看到了,StaticFun incr() 將static 資料成員i 的值累加一。你可以用
一般方式,透過物件來呼叫incr():
StaticFun sf = new StaticFun();
sf.incr();
但由於incr() 是static 函式,所以你也可以直接透過class 加以呼叫:
StaticFun.incr();
某個資料成員被宣告為static 之後,勢必會改變其建立方式(因為static
資料成員對每個class 而言都只有一份,而non-static 資料成員則是每個
物件各有一份)。對static 函式來說,差別反而沒那麼大。Static 函式的
最重要用途之一,就是讓你可以在不建立任何物件的情形下,還可以呼叫
之。這一點很重要,稍後我們會看到,我們得透過main() 的定義,做為
程式的執行起點。
就像任何函式一樣,static 函式可以產生或使用其型別所衍生的具名物
件,所以static 函式常常被拿來當作「牧羊人」的角色,負責看管眾多隸
屬同一型別的一整群物件。
一般而言,當你設計某個class 時,其實就是在描述其物件的外觀長相及行
為舉措。除非以new 來產生物件,否則並不存在任何實質的物件。產生物
件之際,儲存空間才會配置出來,其函式才可供外界使用。
但是有兩種情況,是上述方式所無法解決的。第一種是,你希望不論產生
了多少個物件,或不存在任何物件的情形下,那些特定資料的儲存空間都
只有一份。第二種情況是,你希望某個函式不要和class object 綁在一起。
透過關鍵字static,便可以處理這兩種情況。當你將某筆資料成員或某個
函式宣告為static,它就不再被侷限於所屬的class object 上。所以,即使
沒有產生任何class object,外界還是可以呼叫其static 函式,或是取用其
static data。一般情形下,你得產生某個物件,再透過該物件取用其資料
和函式。所以,non-static 資料/函式必須知道它們隸屬於哪一個物件,才
有辦法運作。由於使用static 函式前並不需要先產生任何物件,所以在
static 函式中不能「直接」取用non-static 資料/函式。如果只是單純地
直接呼叫non-static 函式,而沒有指定某個物件,是行不通的,原因是
non-static 資料/函式總是得和特定的物件綑綁在一起。
118 Thinking in Java www.BruceEckel.com
某些物件導向程式語言,以class data 和class methods 兩個詞彙,代表那
些不和特定物件有所關聯,「其存在只是為了class」的資料和函式。有時
候Java 相關文獻也會使用這兩個詞彙。
只要將關鍵字static 擺在資料成員或函式的定義前,就可以使它們成為靜
態。以下便可以產生一筆static 資料成員,並將它初始化:
class StaticTest {
static int i = 47;
}
現在,即使你產生兩個StaticTest 物件,StaticTest.i 仍然只有一份。產
生出來的那兩個物件會共用同一個i。再看這個:
StaticTest st1 = new StaticTest();
StaticTest st2 = new StaticTest();
此時st1.i 和st2.i 的值一樣,都是47,因為它們都指向同一塊記憶體。
有兩種方法可以取用宣告為static 的變數。一如上例,你可以透過某個物
件來定址,例如st2.i。也可以直接經由其class 名稱完成參考動作— 這種
作法對non-static 成員是行不通的(但對於static 成員卻比較好,因為這
種寫法可以更強調所參考的對象是個static 成員)。
StaticTest.i++;
++運算子會將變數值累加1。經過這個動作,st1.i 和st2.i 的值都是48。
相同的模式可以推廣到static 函式。你可以透過物件來取用某個static 函
式,和取用其他普通的函式沒什麼兩樣。你也可以經由以下特殊語法取用
之:ClassName.method()。定義static 函式的方式和定義static data
member 的方式十分類似:
class StaticFun {
static void incr() { StaticTest.i++; }
}
你看到了,StaticFun incr() 將static 資料成員i 的值累加一。你可以用
一般方式,透過物件來呼叫incr():
StaticFun sf = new StaticFun();
sf.incr();
但由於incr() 是static 函式,所以你也可以直接透過class 加以呼叫:
StaticFun.incr();
某個資料成員被宣告為static 之後,勢必會改變其建立方式(因為static
資料成員對每個class 而言都只有一份,而non-static 資料成員則是每個
物件各有一份)。對static 函式來說,差別反而沒那麼大。Static 函式的
最重要用途之一,就是讓你可以在不建立任何物件的情形下,還可以呼叫
之。這一點很重要,稍後我們會看到,我們得透過main() 的定義,做為
程式的執行起點。
就像任何函式一樣,static 函式可以產生或使用其型別所衍生的具名物
件,所以static 函式常常被拿來當作「牧羊人」的角色,負責看管眾多隸
屬同一型別的一整群物件。
通常,我们创建类时会指出那个类的对象的外观与行为。除非用new创建那个类的一个对象,否则实际上并未得到任何东西。只有执行了new后,才会正式生成数据存储空间,并可使用相应的方法。
但在两种特殊的情形下,上述方法并不堪用。一种情形是只想用一个存储区域来保存一个特定的数据——无论要创建多少个对象,甚至根本不创建对象。另一种情形是我们需要一个特殊的方法,它没有与这个类的任何对象关联。也就是说,即使没有创建对象,也需要一个能调用的方法。为满足这两方面的要求,可使用static(静态)关键字。一旦将什么东西设为static,数据或方法就不会同那个类的任何对象实例联系到一起。所以尽管从未创建那个类的一个对象,仍能调用一个static方法,或访问一些static数据。而在这之前,对于非static数据和方法,我们必须创建一个对象,并用那个对象访问数据或方法。这是由于非static数据和方法必须知道它们操作的具体对象。当然,在正式使用前,由于static方法不需要创建任何对象,所以它们不可简单地调用其他那些成员,同时不引用一个已命名的对象,从而直接访问非static成员或方法(因为非static成员和方法必须同一个特定的对象关联到一起)。
有些面向对象的语言使用了“类数据”和“类方法”这两个术语。它们意味着数据和方法只是为作为一个整体的类而存在的,并不是为那个类的任何特定对象。有时,您会在其他一些Java书刊里发现这样的称呼。
为了将数据成员或方法设为static,只需在定义前置和这个关键字即可。例如,下述代码能生成一个static数据成员,并对其初始化:class StaticTest {
Static int i = 47;
}现在,尽管我们制作了两个StaticTest对象,但它们仍然只占据StaticTest.i的一个存储空间。这两个对象都共享同样的i。请考察下述代码:
StaticTest st1 = new StaticTest();
StaticTest st2 = new StaticTest();
此时,无论st1.i还是st2.i都有同样的值47,因为它们引用的是同样的内存区域。
有两个办法可引用一个static变量。正如上面展示的那样,可通过一个对象命名它,如st2.i。亦可直接用它的类名引用,而这在非静态成员里是行不通的(最好用这个办法引用static变量,因为它强调了那个变量的“静态”本质)。
StaticTest.i++;
其中,++运算符会使变量增值。此时,无论st1.i还是st2.i的值都是48。
类似的逻辑也适用于静态方法。既可象对其他任何方法那样通过一个对象引用静态方法,亦可用特殊的语法格式“类名.方法()”加以引用。静态方法的定义是类似的:
class StaticFun {
static void incr() { StaticTest.i++; }
}
从中可看出,StaticFun的方法incr()使静态数据i增值。通过对象,可用典型的方法调用incr():
StaticFun sf = new StaticFun();
sf.incr();
或者,由于incr()是一种静态方法,所以可通过它的类直接调用:
StaticFun.incr();
尽管是“静态”的,但只要应用于一个数据成员,就会明确改变数据的创建方式(一个类一个成员,以及每个对象一个非静态成员)。若应用于一个方法,就没有那么戏剧化了。对方法来说,static一项重要的用途就是帮助我们在不必创建对象的前提下调用那个方法。正如以后会看到的那样,这一点是至关重要的——特别是在定义程序运行入口方法main()的时候。
和其他任何方法一样,static方法也能创建自己类型的命名对象。所以经常把static方法作为一个“领头羊”使用,用它生成一系列自己类型的“实例”。 ------------------------------------------------------
我们还年轻牛奶会有的奶牛也会有的
可天天在 csdn 混这些会有吗 ??
就是static变量,你可以认为这是一个全局变量