1. 程式人生 > >Java 新手進階:細說引用類型(編程隨想的博客)

Java 新手進階:細說引用類型(編程隨想的博客)

system pan 程序 好的 https [1] css 又是 相同

  在前幾天的帖子《Java性能優化[1]:基本類型 vs 引用類型》裏,俺大概介紹了“引用類型”與“基本類型”在存儲上的區別。昨天有網友在評論中批評說“引用類型變量和它所引用的對象”沒區分清楚,容易混淆。所以今天專門來說一下引用類型的相關細節。
  另外,順便也把原先的帖子中,關於“兩種類型的存儲方式”這節補充了一下,加點插圖,有助於大夥兒的理解。
  其實,引用類型的變量非常類似於 C/C++ 的指針。為了形象起見,也為了打字方便,本文後面的內容,都把“引用類型的變量”稱為【指針】。所以,如果你原先有 C/C++ 背景,今天講的內容對你來說應該很好理解;否則的話,可能要多琢磨琢磨了。

★創建問題

  假設咱們在【函數中】寫了如下這個簡單的語句:

StringBuffer str = new StringBuffer("Hello world");

  別看這個語句簡單,其實包含了如下三個步驟:
  首先,new 操作符會在【堆】(Heap)裏申請了一坨內存,把創建好的 StringBuffer 對象放進去。
  其次,StringBuffer str 聲明了一個指針。這個指針本身是存儲在【棧】(Stack)上的(因為前面俺說了:此語句寫在【函數中】),用來指向某個 StringBuffer 類型的對象。或者換一種說法,這個指針可以用來保存某個 StringBuffer 對象的地址。
  最後,當中這個 等於號(賦值符號)把兩者關聯起來,也就是把剛申請的那一坨內存的地址保存成 str 的值。

  為了加深列位看官的印象,把上次那篇帖子的圖片再拿出來秀一下:

技術分享圖片

★引用對象之間的賦值、判相等

  通過上述的圖解,大夥兒應該明白指針變量和該指針變量指向的【對象】是一個什麽關系了吧?
  還是接著剛才的例子,再來看賦值的問題。對於如下語句:

StringBuffer str2 = str;

  這個賦值語句是啥意思捏?實際上就是把 str 的地址復制給 str2;記住,是地址的復制,StringBuffer 對象本身並【沒有】復制。所以兩個指針指向的是同一個東東。
  再搞一張示意圖,如下(今天畫這些圖可把俺累壞了):

技術分享圖片


  明白了賦值,判斷相等的問題(就是==操作符)也就簡單了。當我們寫如下語句時,只是判斷兩個指針的【值】(也就是對象的地址)是否相等,並【不是】判斷“被指向的對象”是否內容相同。

if(str2 == str)

  實際上兩個指針的值相同,則肯定是指向同一個對象(所以對象內容必定相同)。但是兩個內容相同的對象,它們的地址可能不一樣(比如克隆出來的多個對象之間,地址就不同)。

★final 常量的問題

  針對引用類型變量的 final 修飾符也是很多人搞混淆的地方。實際上 final 只是修飾指針的值(也就是限定指針保存的地址不能變)。至於該指針指向的對象,內容是否能變,那就管不著了。所以,對於如下語句:

final StringBuffer strConst = new StringBuffer();

  你可以修改它指向的對象的【內容】,比如:

strConst.append("hello world");

  但是【不能】修改它的【值】,比如:

strConst = null;

★傳參的問題

  引用類型(在函數調用中)的傳參問題,是一個相當扯的問題。有些書上說是傳值,有些書上說是傳引用。搞得 Java 程序員都快成神經分裂了。所以,我們最後來談一下“引用類型參數傳遞”的問題。
  還是拿剛才的例子,假設現在要把剛才創建的那一坨字符串打印出來,我們會使用如下語句:

System.out.println(str);

  這個語句又是什麽意思捏?這時候就兩說了。
  第一種理解:
  可以認為傳進函數的是 str 這個指針,指針說白了就是一個地址的值,說得再白一點,就是個整數。按照這種理解,就是傳值的方式。也就是說,參數傳遞的是指針本身,所以是傳值的。
  第二種理解:
  可以認為傳進去的是 StringBuffer 對象,按照這種理解,就是傳引用方式了。因為我們確實是把對象的地址(也就是引用)給傳了進去。
  費了這麽多口水,其實不論是“傳引用”還是“傳值”,都可以講得通,關鍵取決於你是【如何看待】參數所傳遞的【東西】。這就好比量子力學中“光的波粒二象性”,如果你以粒子的方式去測量它,它看起來像粒子;如果你以波動的方式去觀測它,它看起來像波動。假如你不太懂量子力學,前面這話就當我沒說 :-)

Java 新手進階:細說引用類型(編程隨想的博客)