1:内容是否可变:val修饰的是不可变的,var修饰是可变的
下面看一段代码,你猜是否有错误
object ValAndVar { |
真实的结果:
- val是不可变的,所以修饰的变量必须初始化
- val是不可变的,所以修饰的变量不能重新赋值
- val是不可变的,所以是多线程安全的
- val是不可变的,不用担心会改变它修饰的对象的状态
- val是不可变的,增强了代码的可读性,不用担心它的内容发生变化
- var是可变的,可以增强代码的灵活性,和val互补
2:val修饰的变量在编译后类似于java中的中的变量被final修饰
先看源代码
object ValAndVar {
val LOVE:String = "篮球"
var SEX:String = _
def main(args: Array[String]): Unit = {
val name:String = "tunan"
var age:Int = 18
}
}再看反编译后的代码(只保留了我们想要的部分)
public final class ValAndVar$ {
public static ValAndVar$ MODULE$;
private final String LOVE;
public void main(String[] args) {
String name = "tunan";
int age = 18;
}
}我们发现这段代码很诡异,scala中的类变量,在字节码层面转换成了 parivate final ,而main方法中的变量却没有添加final修饰,这是否证明编译器有问题?
答案是否定的,对于val或者final都只是给编译器用的,编译器如果发现你给此变量重新赋值会抛出错误。同时字节码(bytecode)不具备表达一个局部变量是不可变(immutable)的能力。
所以就有了现在结果。
3:lazy修饰符可以修饰变量,但是这个变量必须是val修饰的
在证明lazy修饰的变量必须是val之前,我们先看看lazy是什么?
Scala中使用关键字lazy来定义惰性变量,实现延迟加载(懒加载)。
惰性变量只能是不可变变量,并且只有在调用惰性变量时,才会去实例化这个变量。在Java中,一般使用get和set实现延迟加载(懒加载),而在Scala中对延迟加载这一特性提供了语法级别的支持:
lazy val name = initName()
使用lazy关键字修饰变量后,只有在使用该变量时,才会调用其实例化方法。也就是说在定义name=initName()时并不会调用initName()方法,只有在后面的代码中使用变量name时才会调用initName()方法。
如果不使用lazy关键字对变量修饰,那么变量name是立即实例化的,下面将通过一组案例对比认识:
不使用lazy修饰的方法:
object LazyDemo {
def initName:String={
println("初始化initName")
return "返回intName"
}
def main(args: Array[String]): Unit = {
// lazy val name = initName
val name = initName //程序走到这里,就打印了initName的输出语句
println("hello,欢迎来到图南之家")
println(name) //程序走到这里,打印initName的返回值
}
}上面的name没有使用lazy关键字进行修饰,所以name是立即实例化的。
结果:
初始化initName
hello,欢迎来到图南之家
返回intName使用lazy修饰后的方法:
object LazyDemo {
def initName:String={
println("初始化initName")
return "返回intName"
}
def main(args: Array[String]): Unit = {
lazy val name = initName //不调用initName方法,即不打印initName中的输出语句
// val name = initName
println("hello,欢迎来到图南之家") //打印main方法中的输出语句
println(name) //打印initName的输出语句,打印返回值
}
}在声明name时,并没有立即调用实例化方法initName(),而是在使用name时,才会调用实例化方法,并且无论调用多少次,实例化方法只会执行一次。
结果:
hello,欢迎来到图南之家
初始化initName
返回intName证明lazy只能修饰的变量只能使用val
我们发现name都是使用val修饰的,如果我们使用var修饰会怎么样呢?
我们发现报错:
'lazy' modifier allowed only with value definitions
实际上就是认为
lazy
修饰的变量只能val
修饰