Field(幕后属性)
field:幕后字段是自动生成的,它仅仅可以被用在拥有至少一个默认访问器 (getter、setter) 、或者在自定义访问器中通过 field 标识符修饰的属性中。幕后字段可以避免访问器的自递归而导致程序崩溃的 StackOverflowError异常。
为什么会照成这种异常呢?
原因在于在kotlin中,任何时候写了一个变量后面加上等号的代码时,这个等号都会被编译器翻译成调用setter方法,比如:var biao:Int = 1。任何时候当你引用变量时,就会被编译器翻译成调用getter方法。让我们看看代码和反编译成java之后的代码是如何的
class TestKotlinClass {
var biao:Int = 1
get() = biao
set(value) {
if (value >1){
biao = value
}else{
biao = 1
}
}
}
var testKotlinClass = TestKotlinClass()
testKotlinClass.biao = 2
println("了解class-->${testKotlinClass.biao}")
当我们运行这一段代码就会出现StackOverflowError异常。看看反编译之后的Java代码(点击as的菜单栏 Tools/Kotlin/Show Kotlin Betycode/Decompile可以获取)
public final class TestKotlinClass {
public final int getBiao() {
return this.getBiao();
}
public final void setBiao(int value) {
if (value > 1) {
this.setBiao(value);
} else {
this.setBiao(1);
}
}
}
看到这里就很清晰了,在getter和setter里面我们都用到了biao属性,这时候在getter、setter方法形成了递归调用,最终程序会因为内存溢出而中止程序(StackOverflowError异常)
让我们看看使用了field的代码
var biao:Int = 1
get() = field
set(value) {
if (value >1){
field = value
}else{
field = 1
}
}
反编译成Java
private int biao = 1;
public final int getBiao() {
return this.biao;
}
public final void setBiao(int value) {
if (value > 1) {
this.biao = value;
} else {
this.biao = 1;
}
}
可以看出field让getter和setter方法调用了属性而不是递归调用自身方法,从而就不会出现内存溢出的异常
其实在kotlin中getter和setter是自动生成的,而field也是自动生成,所以当我们在定义属性的时候,除非是要对getter和setter做特殊处理,不然不需要写出来。
网友评论