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

最近项目要用到spark平台,无论是看源码还是写程序都需要用scala语言,接触了两天之后,对映射Map这里有点疑问,做了点测试之后记一记自己的想法。

       首先,在scala中定义变量有var和val两种方式,前者定义一个可变量,后者定义一个不可变量,类似Java中的final或者C++中的const,如图1的示例可展示两者的区别。

                                              图1

尝试改变一个val定义的变量会报错。针对var和val的区别应该问题不大。

       然后是对Map类型,在官方api(https://www.scala-lang.org/api/current/)中,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

展开阅读全文
©️2020 CSDN 皮肤主题: 像素格子 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值