什么是Kotlin后台?

作为Java开发人员,后台字段的概念对我来说有点陌生。 鉴于:

class Sample { var counter = 0 // the initializer value is written directly to the backing field set(value) { if (value >= 0) field = value } } 

这个后盾有什么好处? Kotlin的文档说: Kotlin中的类不能有字段。 但是,使用自定义访问器时有时需要有后台字段 。 为什么? 在setter中使用属性名称本身的区别是什么,例如。

  class Sample { var counter = 0 set(value) { if (value >= 0) this.counter = value // or just counter = value? } } 

因为,如果你没有field关键字,你将无法真正地设置/获取get()set(value) 。 它使您能够访问自定义访问器中的后台字段。

这是您的示例的等效Java代码:

 class Sample { private int counter = 0; public void setCounter(int value) { if (value >= 0) setCounter(value); } public int getCounter() { return counter; } } 

显然这并不好,因为二传手本身就是一个无限递归,从不改变任何东西。 记住在kotlin中,只要你写foo.bar = value ,它将被翻译成setter调用而不是PUTFIELD


编辑:Kotlin有属性,而Java有字段 ,这是一个比领域更高层次的概念。

有两种types的属性:一种具有后台字段,另一种没有。

具有后台字段的属性将以字段的forms存储该值。 该字段使存储在内存中的价值成为可能。 这种属性的一个例子是Pairfirstsecond属性。 该属性将改变Pair的内存表示。

没有后台字段的属性将不得不以其他方式存储它们的值,而不是直接将其存储在内存中。 它必须从其他属性或对象本身进行计算。 此属性的一个示例是Listindices扩展属性,它不受字段支持,而是基于size属性的计算结果。 所以它不会改变List的内存表示(因为Java是静态types的,所以它根本无法做到)。

备份字段非常适合在状态更改时运行validation或触发事件。 想想你把代码添加到Java setter / getter的时代。 在类似的情况下,备份字段会很有用。 当你需要控制或者对setter / getters有可见性时,你可以使用后备字段。

当为字段赋予字段名称本身时,实际上是调用setter(即set(value) )。 在你的例子中, this.counter = value会递归到set(value)中,直到我们溢出堆栈。 使用field绕过setter(或getter)代码。

最初,我也很难理解这个概念。 所以让我在一个例子的帮助下给你解释一下。

考虑这个Kotlin类

 class DummyClass { var size = 0; var isEmpty get() = size == 0 set(value) { size = size * 2 } } 

现在,当我们看代码时,我们可以看到它有两个属性,即 – size (带有默认访问器)和isEmpty (带有自定义访问器)。 但它只有一个字段即size 。 为了理解它只有1个字段,让我们看看这个类的Java等价物。

转到工具 – > Kotlin – >在Android Studio中显示Kotlin ByteCode。 点击反编译。

  public final class DummyClass { private int size; public final int getSize() { return this.size; } public final void setSize(int var1) { this.size = var1; } public final boolean isEmpty() { return this.size == 0; } public final void setEmpty(boolean value) { this.size *= 2; } } 

很显然,我们可以看到java类只有isEmpty getter和setter函数,并且没有声明它的字段。 同样在Kotlin中,属性isEmpty没有后台字段,因为属性根本不依赖于该字段。 因此没有支持领域。


现在让我们删除isEmpty属性的自定义getter和setter。

 class DummyClass { var size = 0; var isEmpty = false } 

而上述类的Java相当于

 public final class DummyClass { private int size; private boolean isEmpty; public final int getSize() { return this.size; } public final void setSize(int var1) { this.size = var1; } public final boolean isEmpty() { return this.isEmpty; } public final void setEmpty(boolean var1) { this.isEmpty = var1; } } 

这里我们看到字段sizeisEmptyisEmpty是一个后台字段,因为isEmpty属性的getter和setter依赖于它。