1. 程式人生 > 實用技巧 >為什麼不能從靜態的方法裡面呼叫非靜態方法,或變數?

為什麼不能從靜態的方法裡面呼叫非靜態方法,或變數?

程式最終都將在記憶體中執行,變數只有在記憶體中佔有一席之地時才能被訪問。

類的靜態成員(變數和方法)屬於類本身,在類載入的時候就會分配記憶體,可以通過類名直接去訪問;非靜態成員(變數和方法)屬於類的物件,所以只有在類的物件產生(建立類的例項)時才會分配記憶體,然後通過類的物件(例項)去訪問。

在一個類的靜態成員中去訪問其非靜態成員之所以會出錯是因為在類的非靜態成員不存在的時候類的靜態成員就已經存在了,訪問一個記憶體中不存在的東西當然會出錯:

分類 性質 記憶體分配時機 訪問方式
靜態成員(變數和方法) 類本身 類載入的時候就會分配記憶體 可以通過類名直接去訪問
非靜態成員(變數和方法)
類的物件 類的物件產生(建立類的例項) 通過類的物件(例項)去訪問

而類又是在什麼時候載入的呢?

由引導類載入器負責載入的核心類比如 String 類在 JVM 啟動時(main 方法開始執行前)就會被載入,其它類在使用前(new 它物件或呼叫其靜態方法訪問靜態域等等前)會被動態載入,要注意的是子類被載入前它的所有超類要根據由父到子的順序被逐一載入。

class A1
{
    public static int a=5;
}
class B1 extends A1
{
    public static int a=8;
    void print(){
        System.out.println(
super.a); System.out.println(a); } } public class TestStatic { public static void main(String args[]) { System.out.println("b.a="+B1.a); System.out.println("b.a="+A1.a); new B1().print(); } }


就這段程式碼說一下.

就你上面的程式碼說一下:
當你在doc環境下輸入:
java TestStatic時,
虛擬機器會先載入TestStatic類,此時虛擬機器會先看看TestStatic類有沒有靜態的欄位,
沒有,直接執行main方法。
main方法中第一句程式碼是列印B1.a,
虛擬機器便會去找類B1,找到類B1時,虛擬機發現B1的父親是A1,
於是父親優先,先載入A1,
同樣,在載入A1時,會看看A1中有什麼靜態的東西,有,
static int a = 5;
a是靜態的,先載入,當把靜態的欄位載入完後,一個類就算載入完了,
所以A1已經載入完畢,以後不用在載入了。
父親載入完了,輪到B1了,同樣先看看裡面有什麼靜態的欄位,有,
static int a = 8;
此時B1也載入完畢了。
第一條列印語句到此時也執行完畢了,
輪到第二條列印語句了。
當執行new B1().print();這句時,
會發生動態繫結,
此時會有一個代表B1物件的this物件傳遞給print()方法,
所以print()方法中的
System.out.println(a);
其實是,
System.out.println(this.a);
會打印出一個8出來。
至於super.a就簡單了,
列印父類中的a,
結果是5.
到此,main()方法執行完,整個程式退出。