前言:上一篇中我們介紹了new關鍵字?點擊打開鏈接,new一個類,實際上就是調用該類的構造函數,返回該類的對象。如a = new Animal();返回的對象賦給變量a。我們來分析一下內存分配的步驟,new一個類,實際上就創造了一個對象,就要為這個對象分配內存來存儲成員變量,放在哪里?放在了堆內存中。那么把這個對象賦給a,需要再開辟一塊兒堆內存然后復制成員變量么?答案是否定的。實際上a是一個引用變量,它只存儲內存的地址,系統會讓這個引用變量指向對象的內存,而不會重新開辟。所以,如果希望垃圾回收機制回收某個對象,那么只需要切斷該對象所有引用變量和該對象(該內存空間)的關系,即a=null;內存將會自動被回收。
那么a存放在哪里?a存放在棧中。
this:this關鍵字引用(指向)調用該方法的對象。但倘若this出現在構造器中則是引用該構造器正在初始化的對象。那么this到底有什么用?我們會遇到這種情況,一個方法中需要調用另一個方法,由于調用任何方法都需要對象,那么如果調用的是本方法對象中的另一個方法,則用this關鍵字來表示這個對象。當然,不用this關鍵字,同一個對象中的方法可以相互調用,但是其本質還是隱式的調用了this方法。
那么問題就來了1:static修飾的方法中,是否可以調用非static修飾的成員方法?答案:否,因為調用方法實際上隱式的調用了this來告知對象是誰,但是static修飾的方法是屬于類的,而不是屬于對象的。所以無法找到對應該方法的對象。也就是不能使用this,也就無法調用其他方法了。
那么問題就來了2:static修飾的方法中,是否可以調用static修飾的成員方法?答案:是,因為調用static修飾的方法,實際上默認調用了該類(見點擊打開鏈接),而不是this,又static修飾的方法可以找到該類,所以static調用static是可行的。
如果實在是必須在靜態方法中調用非靜態變量或方法,怎么辦?那就只能在調用的時候重新申請對象:比如
System.out.println(new Animal().foot);那么問題又來了,既然static這么不好使,為什么還要設置static這么個關鍵字?其實,其區別就在于使用static修飾的方法,無論對象是誰,調用的結果都一樣。但是非使用static修飾的方法,不同的對象調用就會不同。比如static修飾了一個變量x,則無論創建多少實例,其調用的都是這個x。但是如果調用普通變量b,那么每次創建實例都要重新給b賦值。因為static變量是屬于類的,其生存周期和類相同,但是普通變量是屬于對象的,其生存周期與變量是相同的,對象不存在了,該變量就不存在了。
成員變量(無論是類變量還是對象變量)都存放在堆中,但是局部變量則存放于棧中,由于局部變量不需要系統垃圾回收,隨著代碼塊兒或者方法的運行結束而結束,所以所占內存比較小。