static關鍵字詳解——static與非static的區別
在本篇部落格中,我主要會講兩個方面的內容,第一個是例項變數與類變數的區別,第二個是例項方法與類方法的區別。大家應該都知道,用static修飾的方法是類方法,用static修飾的變數是類變數。
1.例項變數與類變數的區別
一個類通過使用new關鍵字可以建立多個不同的物件,這些物件將被分配不同的記憶體空間,說得準確些就是不同物件的例項變數將被分配不同的記憶體空間,如果類中有類變數,那麼所有物件的這個類變數都分配給相同的一處記憶體,改變其中一個物件的這個類變數會影響其他物件的這個類變數。也就是說,物件共享類變數。
當Java程式執行時,類的位元組碼檔案被載入到記憶體,如果該類沒有建立物件,類中的例項變數不會被分配到記憶體。但是,類中的類變數 在類被載入到記憶體時,就分配了相應的記憶體空間。如果該類建立物件,那麼不同物件的例項變數互不相同,即分配不同的記憶體空間,而類變數不再重新分配記憶體,所有物件共享類變數,即所有物件的類變數是相同的一處記憶體空間,類變數的記憶體空間直到程式退出執行,才釋放所佔有的記憶體。
類變數是與類相關聯的資料變數,也就是說,類變數是和該類建立的所有物件相關聯的變數,改變其中一個物件的這個類變數就同時改變了其他物件的這個類變數。因此,類變數不僅可以通過某個物件訪問,也可以直接通過類名訪問。例項變數僅僅是和相應的物件關聯的變數,也就是說,不同物件的例項變數互不相同,即分配不同的記憶體空間,改變其中一個例項變數不會影響其他物件的這個例項變數。例項變數只能通過物件來進行訪問。
2.例項方法和類方法的區別
類的方法分為例項方法和類方法兩種,用static修飾的方法是類方法。當類的位元組碼被載入到記憶體的時候,類的例項方法不會被分配入口地址,當該類建立物件後,類中的例項方法才分配入口地址,從而例項方法可以被類建立的任何物件呼叫執行,需要注意的是,當建立一個物件時,類中的例項方法就分配了入口地址,當再建立物件時,不再分配入口地址,也就是說,方法的入口地址被所有的物件共享,當所有的物件都不存在時,方法的入口地址才被取消。
對於類中的類方法,在該類被載入到記憶體時就已經被分配了入口地址,從而類方法不僅可以被類建立的任何物件呼叫,也可以直接通過類名進行呼叫。類方法的入口地址直到程式退出才被取消。
類方法在類的位元組碼被載入到記憶體的時候就分配了入口地址,因此,Java允許直接通過類名來訪問類方法,而例項方法則不能直接通過類名來訪問。類中的類方法不可以操作例項變數,也不可以呼叫例項方法,就是因為在類建立物件之前,例項成員變數還沒有分配記憶體,而例項方法也還沒有入口地址。
如果一個方法不需要操作例項變數就可以實現某種功能的話,那麼這樣的方法就應該宣告為類方法。這樣做可以避免建立物件浪費記憶體。