儲存器的值與引用

聲明一個變量

我們使用 var 來聲明一個變量,就好像從櫃子裡拿出了一個試管放在了實驗台上;

我們給變量規定了一個類型,就好像在試管上貼上了標籤;

那麼放入的試劑就必須是標籤上標記了的——否則可能導致中毒或者爆炸。

同樣的,如果我們試圖給一個儲存器放入一個錯誤的數據類型,那麼編譯器就會報錯——沒錯總有辦法能夠騙過編譯器——反正我不會教你這個方法,那樣就會導致程序崩潰啦。

所以說,試管有容量,我們聲明的類型也有大小限制,超限也會報錯——一般夠用的。

這就是為什麼會有個術語叫做“溢出“。

 

如果你對化學不感興趣

那好,我們換一個栗子:

我們都知道有一些動物是吃草的,而有一些動物則只吃這些吃草的動物?

那麼我這裡有狼和羊,狼要吃羊,而羊要吃草。

你給狼吃草或者給羊吃狼都是不對的………………

好了,我們還是下一個話題吧。

 

對像不是值

現在,我們知道了儲存器是什麼,我們再來說說“放”到儲存器裡的另外一種東西——對象。

在接觸了面向對象編程之後,我們就必鬚麵對一個新的概念——什麼是對象,當然,這個問題我們在上一節課已經討論過了,這節課我們重點來討論如何把大象放進冰箱的問題。

當我們這樣聲明:

難道不是把實例放進了儲存器裡嗎? ——還真不是。

實際上還真的沒有能儲存對象的儲存器,就像我們說的,也沒有能放進大象的家用冰箱。

悄悄告訴你,對像其實放在“堆”上……沒錯,就是垃圾堆。

好了,這裡我們要請出除了 nil 這個特殊的值以外的另一個特殊的值了:

引用

其實引用就是指針。只不過它把指針給包裝了——具體包裝成了什麼我們不清楚——恐怕只有蘋果的攻城獅能告訴你了。總之,我們把這個值叫做引用。

不同於 C 語言的指針,雖然引用也是一個指向堆裡邊某個對象的指針,但它的的確確是不能被直接編輯的。

電視機和遙控器

我談起這兩個東西你可能又覺得古老……正是因為它古老,所以我覺得可能所有人都應該是接觸過的。

當你生成了一個對象,那我們就說你買了一個電視機;那麼對應放到你手裡的,自然就是遙控器啦。所以我們說,不論你的生成的對象實例是多麼複雜,多麼龐大,它的遙控器永遠是那個樣子——頂多多了幾個按鈕(方法)而已,真正的實例其實是放在堆上的。

說到堆

我們再來說一說儲存器裡的引用與堆上對象實例的對應關係。

一般我們聲明一個儲存器,然後賦值給它一個對象,那麼這個儲存器就存了一個引用,然後對象的實例被扔在了堆上。那麼,這時候我們的遙控器和電視機是一對一對應的。

就像這樣,我們從同一個類生成了兩個實例,兩個實例被放在了堆上,而我們手中的變量則存了它們的引用——就像是門牌號。

那如果我要把引用複制一份給別人呢?

沒錯!那麼另外一個變量也就指向了堆上相同的對象!

現在其實 objA 和 objC 是同一個對象的引用呢!

現在我這麼做:

哈!都成了同一個對象! ……等等,那 objB 中原來的對象哪裡去了?這樣豈不是再也沒辦法訪問到它了嗎? ?

沒錯,這個時候 objB 所引用的原來的那個對象就孤零零的存在於堆上——沒關係,它早就被 GC(垃圾收集器)給帶走了(別問我帶到了哪裡)。

做個栗子吧!

其實,就是上節課的課後題啦~

運行結果是24而不再是10.

 

課後題

我們聲明一個叫做 HeapQuiz 的類,這個類只包含一個屬性就是 ID,我們用它來區分實例,現在我們生成了5個實例,然後把它們的引用打亂,現在,你能說出這五個引用對應的實例的 ID 嗎?

 

本文由 落格博客 原創撰寫:落格博客 » 儲存器的值與引用

轉載請保留出處和原文鏈接:https://www.logcg.com/archives/1109.html

關於作者

R0uter

如非聲明,本人所著文章均為原創手打,轉載請註明本頁面鏈接和我的名字。

註釋

發表評論

您的電子郵件地址不會被公開. 必填字段標 *