1. 程式人生 > >關於區域性變數的初始化

關於區域性變數的初始化

我們經常被告知:在Java中的區域性變數必須要先初始化,然後才能使用。為什麼呢?

1. 主記憶體和工作記憶體

Java記憶體模型規定了所有的變數都儲存在主記憶體中,每條執行緒都有自己的工作記憶體。執行緒的工作記憶體中儲存了被該執行緒使用到的變數的主記憶體拷貝,執行緒對變數的所有操作(讀取、賦值等)都必須在工作記憶體中進行,而不能直接讀寫主記憶體中的變數。

可能你會產生一些疑問,平時我們劃分Java記憶體時不都是棧、堆、方法區嗎?沒錯,這無疑是正確的,只不過這裡是從Java記憶體模型的角度來劃分的。

2. 記憶體間互動操作

實際上就是兩個方向:一個變數如何從主記憶體拷貝到工作記憶體;又如何從工作記憶體拷貝到主記憶體。

在Java記憶體模型中定義了8種操作來完成:

  • lock:作用於主記憶體的變數,把一個變數標識為一條執行緒獨佔的狀態
  • unlock:作用於主記憶體的變數,把一個處於鎖定狀態的變數釋放出來,釋放後的變數才可以被其他執行緒鎖定。
  • read:作用於主記憶體的變數,把一個變數的值從主記憶體傳輸到執行緒的工作記憶體中,以便隨後的load操作使用
  • load:作用於工作記憶體的變數,把read操作從主記憶體中得到的變數值放入到工作記憶體的變數副本中
  • use:作用於工作記憶體的變數,把工作記憶體中的一個變數的值傳遞給執行引擎
  • assign:作用於工作記憶體的變數,把一個從執行引擎接收到的值賦給工作記憶體的變數(即遇到給變數賦值的位元組碼指令)
  • store:作用於工作記憶體的變數,把工作記憶體中一個變數的值傳送到主記憶體,以便以後的write操作使用
  • write:作用於主記憶體的變數,把store操作從工作記憶體中得到的變數放入到主記憶體的變數中

3.  執行以上8種操作的規則

    規則有很多,我們這裡只貼出兩條:

    a. 一個新的變數只能在主記憶體中誕生,不允許在工作記憶體中直接使用一個未被初始化的變數,即對一個變數實施use、store操作之前,必須先執行過了load和assign初始化操作。

    b. 不允許一個執行緒丟棄它最近的assign操作,即變數在工作記憶體中改變了之後必須把該變化同步會主記憶體。

當我們通過“int[] k;”語句來定義一個變數k時,k只是存在於工作記憶體中。根據規則a中提到的,新變數必須誕生於主記憶體。在我們要使用這個k變數時,比如這裡的輸出操作,必須要執行assign操作,即賦值初始化。

注意:若是隻定義不使用,不會報錯