我在网上看了很多概念性文章,下面来写一下自己的理解
那么首先我们先用java代码解释一下什么是字段
class Computer{
//这里name就是字段,用于装载数据使用的,一般我们定义为私有的
private String name;
//这里的getter和setter或者其他访问器供与外部使用的就是所谓的属性
public void setter(String name){}
public String getter(return this.name){}
}
还是不怎么懂吧,没事我们直接上代码
首先我们写一个kotlin代码
案例1:
class Game{
var name: String?=null
get() = name
set(value){
name = value
}
}
如果你拷贝了以上代码的话,你就会发现在get()和set()是recursive无限递归的代码,为什么会这样呢
我们先使用IDEA将此kotlin转为字节码,如图下所示
Decomplie后,将会转换为java代码,瞧瞧我们发现了什么
从以上转换后的JAVA代码中,我们看到无论是get还是set方法都进入了死循环中。文章末尾解释说明,我们先继续往下走
案例2:
class Game{
var name: String = ""
get() {
return field //kotlin的幕后字段用field表示,那它有什么用呢,下面揭晓
}
set(value){
field = value
}
}
以下就是转换为java的代码,
public final class Game {
@NotNull
private String name = "";
@NotNull
public final String getName() {
//注意此处返回的是this.name而不是this.getName(),这个就是filed的作用
return this.name;
}
public final void setName(@NotNull String value) {
this.name = value;
}
}
这里顺便可以大家说下其他有趣的测试用例
有趣案例1:
var name: String?=null//当案例中name如果这么声明的话
//setName中回增加一个非空判断方法,这也就是?这种可以为空的安全类型,在java其实都有判断的
Intrinsics.checkParameterIsNotNull(value, "value");
有趣案例2:
方法如果没有声明open的话,所有方法在java中默认是final修饰
有趣案例3
class Game{
var name: String?=null
get() {
return "CSGO"
}
set(value) {
print("ENTER THE GAME")
field= value
}
}
fun main(args: Array<String>) {
val game = Game()
//kotlin调用set get方法可以直接用.字段
game.name="DOTA" //测试赋值的时候会不会默认调用set方法
//OUTPUT:ENTER THE GAME
}
//从侧面证明为什么案例1中不加field会无限调用,再来看看案例1的代码
class Game{
var name: String?=null
get() = name
set(value){
name = value
}
}
//如果我想要给name赋值为"LOL",name="LOL"在kotlin中它会自动帮你调用set方法,而在你调用set的时候,kotlin又会帮你调用set的set方法,所以导致无限调用,使用field就是告诉kotlin,我用this.字段来接收数据的