scala中的var,val,immutable,mutable理解小結

       最近項目要用到spark平臺,無論是看源碼還是寫程序都需要用scala語言,接觸了兩天之後,對映射Map這裏有點疑問,做了點測試之後記一記自己的想法。

       首先,在scala中定義變量有var和val兩種方式,前者定義一個可變量,後者定義一個不可變量,類似Java中的final或者C++中的const,如圖1的示例可展示兩者的區別。


圖1

       嘗試改變一個val定義的變量會報錯。針對var和val的區別應該問題不大。

       然後是對Map類型,在官方api中,Map的子類中至少可以分爲可修改mutable和不可修改immutable兩大類Map,在子類中除了HashMap,SortedMap等具體實現外,還有同名的子類類型Map,默認的,定義一個Map類型的變量(我更想說引用,不知道scala有沒有這樣的概念),其類型是不可修改的,如果要定義一個可修改類型的需要顯示指出,如圖2所示。


圖2

       mutable和immutable的區別從命名可初步瞭解,前者可對內容進行修改,後者初始化之後便不可修改。如圖3所示,對圖2中的map和mmap進行添加元素操作,map嘗試+=操作的時候失敗了,而mmap成功修改了內容,添加了“("cc" -> 3)”元素。查看官方文檔其實能很快了解,因爲“+=”操作符或者函數是mmap的成員(函數),但不是map的成員(函數),這也很好理解,既然我map是一個immutable的類型,爲什麼還要提供給你一個諸如“+=”能修改自身內容的函數或者成員。但是這裏有一個問題,mmap和map都是val類型,爲什麼“+=”能修改mmap?這裏先不展開,標記爲問題1,後面我會繼續討論。


圖3

       一般來說,對immutable和mutable的Map類型變量進行“+”、“-”操作會返回一個操作後的,類型跟原來一樣的新的Map變量,而不改變原來的變量,如圖4所示。


圖4

       最後,來到我們的問題了,也就是一個問題1的拓展,假設定義一個var的immutable變量,或者是一個val的mutable變量又如何?一開始可能會被哪些是可變哪些是不可變混暈,但是仔細想想其實也很好懂。

       先拋出我的看法:

       1)val和var只是表明定義的變量(引用!!!)是否能被修改而指向其他內容,這就是我上面說的爲什麼我更願意用引用這個概念來稱呼變量這個叫法。

       2)mutable和immutable表明的是內存中開闢出來的這塊空間裏的內容能否被修改。如果你有點C++或者Java的基礎,對new出來堆空間概念有點理解,估計我們就能達成共鳴了。

       按照我自己的理解(不能保證正確,但是感覺方便理解),上述map和mmap及其內容的內存分佈可以假設如下:


圖5

       val和var是指虛框1中內容,其中val是指指向一個內容之後,就不能改變讓其指向其他內容,比如map;而var是指指向一個內容後,可以隨意改變指向其他內容,如圖所示。


圖6

       immutable和mutable是針對虛框2中的內容來說纔有意義的。比如對於mmap來說,使用“+=”添加一個“("fc -> 3")”對偶,則表示爲圖7所示


圖7

       mmap指向的區域沒有變,只是修改了該區域中內容。對於immutable類型定義的區域,不能修改內容。回顧上述提到的問題1,用immutable.Map的var變量來修改如何,比如

                                   var map =Map("aa" -> 1, "bb" ->2)

                                   map +=("cc" -> 3)

       前面我們運行過,對immutable.Map類型的變量使用“+=”會報錯,提示沒有該成員。但是上述兩行代碼是正確的,而且注意到map的確被修改了內容,如圖8所示。


圖8

       這是爲什麼呢?其實原理很簡單,這是因爲map指向的區域變化了,因爲map是個var變量,上述操作分兩部分:第一步用“map + ("cc"-> 3)”返回一個新的immutbale區域;第二步:將map指向新的immutable區域。如圖9所示,而原來的immutable區域內容沒有變,只是在以後某個時候被JVM的GC機制回收。


圖9

       至此,var,val,mutable,immutable四種情況的內存變量變化已經說明完畢,內容有點亂,但是如果還是不明白,可以參考java中“==”與“equals”區別時候的內存佈局和引用變化情況,個人感覺原理上是一樣的。另外,因爲使用“==”比較時中如果是同一個內容區域,也就是hashCode相同纔會返回true,爲了佐證圖7和圖9,做最後一個測試,大家隨意感受一下。


圖10


圖11

發佈了56 篇原創文章 · 獲贊 27 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章