现在的位置: 首页 > 综合 > 正文

JAVA的STATIC[ZZ]

2013年10月04日 ⁄ 综合 ⁄ 共 3573字 ⁄ 字号 评论关闭
昨天上JAVA課程.被有STATIC和沒有STATIC搞到頭暈.老實說老師的解釋偶也聽不懂..所以今天去找了相關的資料....結果...還是不太懂.
PO上來大家看看.也許會對一些人有幫助....:cool:
來源: http://www.oreilly.com.tw/sleepless/static.html

Static 的意義與實作方式
「將某 class 產生出一個 instance 之後,此 class 所有的 instance field 都會新增一份,那麼所有的 instance method 是否也會新增一份?」我常常看到網路上有人在討論此問題,所以寫了這篇文章,以為解釋。

Member 的種類
類別(class)的內部組成統稱為成員(member),如果依據成員是「資料」還是「程式」來區分,可以分成:

資料,被稱為 field
程式,被稱為 method
如果再依據有無使用static修飾而細分,則成員可細分成四種:

class field:有用static修飾的field
class method:有用static修飾的method
instance field:沒有用static修飾的field
instance method:沒有用static修飾的method
顧名思義,class field/method和class本身有密切的關係,而instance field/method則與instance(也就是物件)有密切的關係。請看下面的範例程式。

public class Class1 {

 public static int classField;

 public static void classMethod1() {

  // ...
 }
 public static void classMethod2() {
  // ...
 }
 public int instanceField;
 public void instanceMethod1() {
  // ...
 }
 public void instanceMethod2() {
  // ...
 }
}

public class Class2 {
 public static void classMethod () {
  // ...
 }
 public void instanceMethod() {
  // ...
 }
}

Field
宣告field時,如果前面加上static的修飾字,就會使得此field變成是class field。一個class field永遠只佔用一塊記憶體,而且此記憶體空間是在此class一被載入(load)記憶體之後就立刻配置的(allocate),感覺就如同此field與該class本身相關,而不是與該class的instance相關。class field可以被同一個class的class method內部所直接使用,舉例來說,上述的classMethod1()內部可以出現classField。如果Class1的class method或instance method欲使用到Class2的class field,就必須在前面冠上Class2,例如:Class2.classField。

宣告field時,如果前面「不」加上static的修飾字,就會使得此field變成是instance field。對instance field而言,每產生一個instance(物件)就多一塊instance field的記憶體,每少一個instance就少一塊instance field的記憶體。instance field可以被同一個instance的instance method內部所直接使用,舉例來說,上述的instanceMethod1()內部可以出現instanceField。如果某class的class method或instance method欲使用到某instance的instance field,就必須在前面冠上instance名稱,例如:obj.classField。

Method
宣告method時,如果前面加上static的修飾字,就會使得此method變成是class method。對class method而言,永遠只佔用一塊記憶體,而且此記憶體空間是在此class一被載入進記憶體之後就立刻配置的,就如同此method是與該class本身相關,而不是與該class的instance相關。class method可以被同一個class的任何class method內部所直接使用,舉例來說,上述的classMethod1()內部可以出現classMethod2()。如果Class1的class method或instance method欲使用到Class2的classMethod(),就必須在前面冠上Class2,也就是Class2.classMethod()。

宣告method時,如果前面「不」加上static的修飾字,就會使得此method變成是instance method。對instance method而言,每產生一個instance「並不會」多一塊instance method的記憶體。同一個method不管被調用(invoke)幾次,也不管被調用時的instance是何者,每次的程式碼完全都一樣,差別只在每次執行時資料不同,而資料是存放在call stack中,所以不會混淆。在instance method內,資料的來源包括了參數和instance field。參數被傳進來變成call stack內的entry,所以不會混淆,這很容易理解,但是instance field是如何區隔開來的(前面剛提過:instance field會隨著instance數目增加而增加),這是透過隱匿(implicit)的this參數來達到了,稍後會有說明。instance method可以被同一個instance的instance method內部所直接使用,舉例來說,上述的instanceMethod1()內部可以出現instanceMethod2()。如果某class的class method或instance method欲使用到某instance的某instance method,就必須在前面冠上此instance名稱,例如:obj.classMethod()。

隱匿的 this 參數
綜合上面的敘述來看:

class field:共用一塊記憶體
class method:共用一塊記憶體
instance field:隨著每個instance各有一塊記憶體
instance method:共用一塊記憶體
instance method為什麼不是隨著每個instance佔有一塊記憶體,反倒是共用一塊記憶體?其實,讓每個instance method如同instance field一樣,隨著每個instance佔有一塊記憶體,這麼做當然是可以的,只是Java編譯器和JVM都不這麼做,因為太浪費記憶體空間了。一個field少則佔用一個byte,多則佔用數百Byte,但是method少則數個byte,多則數百Kilo Byte。Mehtod耗費的記憶體是field的數百倍,甚至數千倍,當然是能共用就盡量共用,比較不會消耗記憶體。既然JVM讓一個class的所有instance共用相同的instance method,下面兩行程式碼在instanceMethod()內部時,如何區分是instance1或instance2?

instance1.instanceMethod();
instance2.instanceMethod();

因為編譯器會幫我們在把instance1和instance2個別傳入instanceMethod()中當作第一個參數。也就是說,任何instance method參數的實際個數都會比表面上多一個,這個多出來的參數是由Java編譯器幫我們加上去的,用來代表對應的instance。此參數的變數名稱為this,也是Java的一個關鍵字(keyword)。

當調用某個instance method或使用某個instance field時,你必須在前面加上該instance的名稱,如果該instance method/field相關的instance和當時程式碼所在的instance method的instance指的是同一個instance時,該instance的名稱就是this,這種情況下,你也可以選擇不在前面加上「this.」。

然而,在某些狀況下,非得在前面加上「this.」不可。例如,當method中的參數或區域變數和instance field名稱完全相同時,如果不在前面冠上「this.」,那麼指的是參數或區域變數;如果在前面冠上「this.」,那麼指的才是instance field。

抱歉!评论已关闭.