《Kotlin核心编程》 ——2.2 val和var的使用规则

举报
华章计算机 发表于 2020/02/21 20:20:57 2020/02/21
【摘要】 本节书摘来自华章计算机《Kotlin核心编程》 —— 书中第2章,第2.2.1节,作者是水滴技术团队 。

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声明一个指向数组的变量,然后尝试对其进行修改。

>>> val x = intArrayOf(1, 2, 3)

>>> x = intArrayOf(2, 3, 4)

error: val cannot be reassigned

>>> x[0] = 2

>>> println(x[0])

2

因为引用不可变,所以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类的对象,如下编写方式会变得更加直观:

class Book(var name: String) {  // 用var声明的参数name引用可被改变

    fun printName() {

        println(this.name)

    }

}

 

fun main(args: Array<String>) {

    val book = Book("Thinking in Java") // 用val声明的book对象的引用不可变

    book.name = "Diving into Kotlin"

    book.printName() // Diving into Kotlin

}

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


【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。