java中的static關鍵字說清楚還得靠JVM

語言: CN / TW / HK

持續創作,加速成長!這是我參與「掘金日新計劃 · 6 月更文挑戰」的第2天,點選檢視活動詳情

前言

  • Java中Static想必大家一定使用過吧。他是用來修飾類或者成員變數或者方法的。
  • 關於Static的用法還是很簡單的,因為他就是一個修飾詞。但是如果不理解他修飾的作用原理的話,可能會鬧出bug來

變數

image-20220509191420226.png

  • 上圖是一個簡化的JVM記憶體結構模型。學習過JVM的都知道我們建立的物件正常情況下都是在堆中的。那麼我們訪問物件中的屬性自然也就存放在堆中的。
  • 但是當static修飾屬性之後他就發生了變化了。

​  class Demo {    //成員變數    public int num = 100;    //靜態成員變數    public static int count = 200;    //靜態方法    public static void method(){   System.out.println(count);   }  }

  • num屬性屬於常規屬性,count屬性屬於靜態變數。他們不僅僅是名稱上的不同。從JVM的角度看他的存放位置也不同。
  • 首先num依賴於具體的物件,所以他和物件存放在一起都是堆中。
  • 而count獨立於物件。JVM中專門有一塊空間用於存放靜態變數。這個空間我們叫做方法區。

方法

  • 除了修飾變數外,static還可以修飾方法。被修飾的方法我們叫做靜態方法 。靜態方法的特點和靜態變數一樣都屬於類而不是物件。靜態方法內部只能訪問靜態變數而無法通過this物件進行訪問物件屬性。
  • 總結下來就是靜態方法內部只能訪問靜態變數無法訪問非靜態變數。
  • 除了靜態方法外,還有一個特殊的方法叫做靜態程式碼塊。這個方法不需要我們準備方法名,入參,出參等等。只需要準備方法體。關於方法體內部和靜態方法內部要求是一樣的。

image-20220514140752124.png

  • 關於靜態程式碼塊和靜態方法他們和普通方法還有一個重要的區別就是執行時機。靜態變數與普通變數的區別就是記憶體分佈位置,而方法是在棧中操作的,不涉及記憶體的儲存,所以區別就是方法執行的時機。這裡需要我們提前瞭解點類載入機制。
  • 首先我們一個類的載入分為五個過程。首先是載入class元資訊,最後一步是進行初始化。至於前面三步我們這裡可以不理解。重點知道在類載入的最後階段會進行初始化,而初始化的操作就是執行靜態方法和靜態程式碼塊。
  • 從類載入過程中我們也能夠看的出來靜態方法是不依賴於物件的呼叫的。因為靜態方法中只能使用到靜態屬性。也就是說靜態屬性使用時還沒有建立物件。這也佐證了靜態變數不依賴物件的說法。

總結

  • 本文主要講解Java基礎,請原諒我沒有華麗的詞藻渲染出色的文章。雖然基礎但往往是我們容易忽略的知識點。
  • 只有不斷的學習,才能不斷的進步,關於static的進一步使用場景,目前我能想到的就是單例模式中會使用。
「其他文章」