Kotlin学习系列之:理解Backing Field

x33g5p2x  于2022-03-08 转载在 其他  
字(1.2k)|赞(0)|评价(0)|浏览(396)

对于Backing Field这个概念,在Java中是没有的,是Kotlin中新引入的概念。我们先来看看它在什么情况下使用:

class Person {

    var username: String = "hello"
    get() {
        println("getter invoked...")
        return field
    }
    set(value) {
        println("setter invoked...")
        field = value
    }
}

要想理解Backing Field,首先要明确一点:在Java中,通常将域(成员变量,Field)和它的访问器(Setter/Getter)联合起来称作是属性(Property);但是在Kotlin中,属性是作为一级语言特征,完全替代域和访问器的概念。

举个例子,我们定义一个类:

class User(val name: String, var age: Int)

然后我们在main函数中使用它:

fun main(args: Array<String>){
    val user = User(“zhangsan”, 25)
    println(user.name)
    user.age = 29
    println(user.age)
}

可以看出,无论是获取还是改变这个User里的age,从字面上看来都是age这个属性,都是它本身,是把它当做是不可分割的整体。而在Java中,要想实现前面的一样的效果,是需要有三部分:首先你得声明一个成员变量(域),然后为其生成对应的set、get方法才能实现读取和更新的功能。

明确了这两点之后,Backing Field的作用就可以体现了,类比到Java上,就是你声明的那个成员变量,是真正存储属性值的地方。

###2018.12.11更新###

明确了这两点之后呢,实际上我们可以发现,在使用属性的地方是不需要关注这个Backing Field的:像user.age = 29这种,这个时候就会触发age的set()方法的调用;像println(user.age)这行代码一样,这个时候就会触发name的get()方法的调用。无论set还是get,我们都是使用这种形式user.age。正如前面所说的,Kotlin中属性是作为一级语言特性的,属性包含了域、set和get方法三个部分,对于使用者来说是很方便的。而我们在需要自定义get、set方法时,我们又是需要区分这三者的,就拿set方法来说:如果这个地方你不知道field字段(也就是Backing-field),你不写成field = value,那你会怎么写?那只能写成这样:

注意左边红框中这个标识,在IDEA里面就表示递归调用了。如果在写这样的main函数进行测试的话:

最终肯定会内存溢出的。

所以,backing field代表的就是原来Java中的那个实际存储数据的成员变量!

相关文章