Kotlin编程实战:创建优雅、富于表现力和高性能的JVM与Android应用程序
上QQ阅读APP看书,第一时间看更新

2.3 选择val而不是var

要定义一个不可变的变量——即常量或值,使用val,如下所示:

与Java不同,Java将类型放在变量名之前,而在Kotlin中,首先放置变量名,然后是冒号,然后是类型。Kotlin认为Java要求的顺序是“本末倒置”,并且更加强调变量名而不是变量类型。

由于变量的类型在此上下文中很明显,我们可以省略类型说明,并要求Kotlin使用类型推断:

无论使用哪种方式,pi的值都不能修改。val就像Java中的final。任何试图对使用val定义的变量的值进行修改或重新赋值都会导致编译错误。例如,以下代码是无效的:

如果我们想改变一个变量的值该怎么做呢?为此,Kotlin使用var——也称为“羞耻的关键字”。使用var定义的变量可以随意变化。

下面的脚本创建了一个可变的变量,然后修改它的值:

可变变量是命令式编程的一种生活方式。但这在函数式编程中是一个禁忌。一般来说,选择不变更好——也就是说,val优于var。这里有一个例子来说明为什么这样更好:

不要运行代码,相反,仔细观察它,把它展示给你的一些同事,并询问代码的输出将是什么。对此做一个投票。输出将等于大多数人所说的那样——只是开个玩笑。我猜值得庆幸的是,程序的正确性不是一个民主的过程。

你的投票结果大概有三个答案:

□输出是4。

□我想输出是0。

□这段代码最近在某人身上引起的什么。

上面代码的输出是0——也许你猜对了,但是在编码时猜测并不是一个令人愉快的活动。

可变性使得代码难以推理。具有可变性的代码也有较高的出错概率。带有可变变量的代码更难并行处理。一般来说,尽量使用val而不是var,稍后你会看到Kotlin在不同的实例中默认使用val和不可变性。

尽管Kotlin中的val与Java中的final非常相似,但与Java不同的是,Kotlin坚持用var标记可变变量,这使得在Kotlin中寻找var的存在比在Java中寻找final的缺失更容易。因此,在Kotlin中,更容易检查代码中可能由于可变性而产生的潜在错误。

但是,关于val需要注意的是——它只是使变量或引用成为常量,而不是所引用的对象。因此val只保证引用的不变性,并不阻止对对象的修改。例如,String是不可变的,但StringBuilder不是。无论使用val还是var,String的实例是安全的,不会被修改,但StringBuilder的实例则不是。在下面的代码中,变量message是不可变的,但是它引用的对象是可以使用该变量进行修改的。

简而言之,val只关注手头的变量或引用,而不是它所指的内容。然而,在可能的情况下,尽量选择val而不是var。