美文网首页
2.2 val和var的使用规则

2.2 val和var的使用规则

作者: AndYMJ | 来源:发表于2021-07-03 20:54 被阅读0次

与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章关于只读集合的介绍中发现一种思路。

相关文章

  • 2.2 val和var的使用规则

    与Java另一点不同在于,Kotlin声明变量时,引入了val和var的概念。var很容易理解,JavaScrip...

  • Kotlin最基本用法

    val 和 var 的使用规则如果说 var 代表了 varible(变量),那么 val 可看成 value(值...

  • 二.基础语法

    2.1不一样的类型声明 2.2val和var的使用规则 2.3高阶函数和Lambda 2.4面向函数式编程 2.5...

  • 读书笔记《Kotlin核心编程》

    1. 重点理解val的使用规则 引用1 如果说var代表了varible(变量),那么val可看成value(值)...

  • Kotlin如何预防空指针和解决“!!”

    用Val而不是Var在 Kotlin 中 val 代表只读,var 代表可变。建议尽可能多的使用 val。val ...

  • val 和 var

    回到目录项目源码 kotlin-basics 项目ValVarDemoTest 源码地址 Kotlin 中使用 v...

  • Kotlin中的变量、常量、const

    变量和常量 在Kotlin中使用val和var关键字来声明变量,其语法如下: val|var 变量名[: 变量类型...

  • Kotlin秘籍之变量

    Kotlin中怎样声明一个变量 kotlin中声明变量需要使用val和var关键字 例如: var 和 val的区...

  • Kotlin 学习笔记

    var 和 val (Declaring Properties) val and var are the two...

  • Kotlin中的变量属性

    变量的定义 类中的属性可以用val和var来表示var代表可读写的val代表只读 案例 使用/调用 Getter和...

网友评论

      本文标题:2.2 val和var的使用规则

      本文链接:https://www.haomeiwen.com/subject/zskpultx.html