2.2 val和var的使用规则

与Java另一点不同在于,Kotlin声明变量时,引入了val和var的概念。var很容易理解,JavaScript等其他语言也通过该关键字来声明变量,它对应的就是Java中的变量。那么val又代表什么呢?

如果说var代表了varible(变量),那么val可看成value(值)的缩写。但也有人觉得这样并不直观或准确,而是把val解释成varible + final,即通过val声明的变量具有Java中的final关键字的效果,也就是引用不可变。

-------------------

提示: 我们可以在Intellij IDEA或android studio中查看val语法反编译后转化的Java代码,从中可以很清楚的发现它是用final实现这一特性的。

-------------------

2.2.1 val的含义:引用不可变

val的含义简单,但依然会有人疑惑。部分原因在于,不同语言跟val相关的语言特性存在差异,从而容易导致误解。

我们先用val声明一个指向数组的变量,然后尝试对其进行修改。

因为引用不可变,所以x不能指向另一个数组,但我们可以修改x指向数组的值。如果你熟悉Swift,自然还会联想到let,于是我们再把上面的代码翻译成Swift的版本。

let x = [1,2,3]

x = [2,,3,4]

Swift::Error:cannot assign to value:‘x’ is a ‘let’ constant

x[0] = 2

Swift::Error:cannot assign through subscript :‘x’ is a ‘let’ constant

这下连引用数组都不能修改了,这是为什么啦?

其实根本的原因在于这两种语言对数组采用了不同的设计。在swift中,数组可以看成一个 值类型,它与变量x的引用一样,存在栈内存上,是不可变的。而kotlin这种语言的设计思路,更多考虑数组这种大数据的拷贝成本,所以存储在堆内存中。

因此,val声明的变量是只读变量,他的引用不可更改,但并不代表其引用对象也不可变。事实上,我们依然可以修改引用对象的可变成员。

我们可以把数组换成一个Book类的对象,如下编程方式变得更加直观:


-------------------

首先,这里展示了Kotlin中的类不同于Java的构造方法,我们会在第三章中介绍关于具体的语法。其次,我们发现var和val还可以用来声明一个类的属性,这也是kotlin中一个非常有个性的语法,你还会在后续的数据类中再次接触到它的应用。

------------------

2.2.2 优先使用val来避免副作用

在很多Kotlin的学习资料中,都会传递一个原则:优先使用val来声明变量。这相当正确,但更好的理解可以是: 尽可能采用val、不可变对象及纯函数来设计程序。关于纯函数的概念,其实就是没有副作用的函数,具备引用透明性,我们会在第10章专门探讨这些概念。由于后续的内容我们会经常使用副作用来描述程序的设计,所以我们大概了解一下什么叫副作用。

简单来说,副作用就是修改了某处的某些东西,比方说:

1.修改了外部变量的值

2.IO操作,如写数据到磁盘。

3.UI操作,如修改了一个按钮的可操作状态

来看一个实际例子:我们先用var来声明一个变量a,然后count函数内部对其进行自增操作。

var a =1

fun count(x:Int){

a =a +1

    Log.i("count", (a+x).toString())

}

count(1) = 3

在以上代码中,我们会发现多次调用count(1)得到的结果并不相同,显现这是受到了外部变量a的影响,这个就是典型的副作用。如果我们把var换成val,然后再次执行类似的操作,编译就会报错。

这就有效避免了之前的情况。当然,这并不意味着用val声明变量后就不能再对该变量进行赋值,事实上,Kotlin也支持我们在一开始不定义val变量的取值,随后在进行赋值。然而,因为引用不可变,val声明的变量只能被赋值一次,且在声明时不能省略变量类型,如下所示:

运行结果 = 1

不难发现副作用的产生往往与 可变数据 及 共享数据 有关,有时候它会使得结果变得难以预测。比如,我们在采集多线程处理高并发的场景,“并发访问”就是一个明显的例子。然而,在Kotlin编程中,我们推荐优先使用val来声明一个本身不可变的变量,这在大部分情况下更具有优势:

1. 这是一个防御性的编码思维模式,更加安全和可靠,因为变量的值永远不会在其他地方被修改(一些框架采用反射技术的情况除外)

2. 不可变的变量意味着更加容易推翻,越是复杂的逻辑,它的优势就越大。

回到Java中进行多线程开发的例子,由于Java的变量默认是可变的,状态共享使得开发工作很容易出错,不可变性则可以在很大程度上避免这一点。当然,我们说过,val只能确保变量引用的不可变,那如何保证引用对象的不可变性?你会在第6章关于只读集合的介绍中发现一种思路。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,254评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,875评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,682评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,896评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,015评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,152评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,208评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,962评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,388评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,700评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,867评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,551评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,186评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,901评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,142评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,689评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,757评论 2 351

推荐阅读更多精彩内容