1. 前言
刚开始接触 Kotlin 时,常听人说 Kotlin 中的 val
就是 Java 中的 final
;随着对 Kotlin 的学习,慢慢知道这句话多么误导人。文章会从几个方面对比 Kotlin 的 val
和 Java 的 final
的区别:变量声明,属性声明,函数参数,委托属性。
2. 正文
2.1 变量声明
分别在 .java 文件和 .kt 文件中声明一个变量,看一下区别:
public class Test {
public static void main(String[] args) {
final int x = 5;
// x = 6; // Cannot assign a value to final variable 'x'
}
}
fun main(args: Array<String>) {
val x: Int = 5
println(x)
// x = 6 // val cannot be reassigned
}
可以看到 final
修饰的 int
不可以被再次赋值;val 声明的 x
也不可以被再次赋值。现在看来,两者倒是有一定的共性。
2.2 属性声明
同样看一下例子:
Kotlin 的例子:
class Man {
var age: Int = 17
val isAdult: Boolean
get() = age >= 18
}
fun main(args: Array<String>) {
val man = Man()
println(man.isAdult)
man.age = 18
println(man.isAdult)
}
/*
打印结果:
false
true
*/
Java 的例子
public class Man {
int age;
final boolean isAdult = false;
public static void main(String[] args) {
Man man = new Man();
System.out.println(man.isAdult);
}
}
对比两个例子,可以看到 isAdult
虽然在 Kolin 中声明为 val
,但是它的值依然是可以变化的;而 Java 中声明为 final
的 isAdult
字段就不具备这个能力了。
2.3 函数参数
Kotlin 的例子:
fun release(animator: ValueAnimator) {
animator.cancel()
animator = null // 编译报错:val cannot be reassigned
}
Java 的例子:
public class Utils {
public static void release(ValueAnimator animator) {
animator.cancel();
animator = null;
}
public static void release1(final ValueAnimator animator) {
animator.cancel();
animator = null; // // Cannot assign a value to final variable 'animator'
}
}
可以看到在 Kotlin 中函数的参数默认就是 val 的,不可以再修改这个参数,而 Java 中必须要加上 final,才能有这个效果。
2.4 委托属性
Kotlin 中原生支持委托属性。
val lazyValue: String by lazy {
println("computed")
"Hello"
}
fun main(args: Array<String>) {
println(lazyValue)
println(lazyValue)
}
而 Java 却却必须自己写代码实现。
Kotlin 中是有 final 关键字的,它的含义是相关成员不能被重写,类中成员默认使用。也可以显式地使用,用于重写方法禁止再被重写。
在 Kotlin 中的类和方法默认都是 final 的。
3. 最后
Java 中的 final 只能和 Kotlin 中 val 声明属性的一种情况相等。换句话说,val 包括的东西要比 Java 中的 final 多得多。需要特别说明的是,在 Kotlin 中是存在 final 这个关键字的。它的含义是相关成员不能被重写,类中成员默认使用。也可以显式地使用,用于重写方法禁止再被重写。在 Kotlin 中的类和方法默认都是 final 的。