kotlin中属性声明getter、setter、backing field Kotlin 支持后备属性和委托属性它们允许你在不直接使用字段的情况下管理属性。1、后备属性修饰符gettersetterbacking fieldval✅ 有❌ 无视情况有var✅ 有✅ 有视情况有backing field幕后字段即 field只在 getter/setter 中实际访问了它时才会生成如果 getter 是纯计算如 get() x 1 且没读 field编译器就不会分配那个存储字段。var name: String get() field // ✅ 读那块存储 set(v) { field v } // ✅ 写那块存储 // field 只在 getter/setter 内部可用不是关键字是一个上下文相关的隐式变量。 // var可同时定义 get set var name: String get() field.uppercase() set(value) { field value.trim() } // val只能定义 get写 set 会编译错误 val id: Long 0L get() field // set(v) { ... } // ❌ 不能写写法有 backing field原因var x: Int 0✅var 必须能存要存就得有字段val x: Int 0✅val 初始化后值固定要存初始值val x: Int get() 42❌getter 不依赖任何存储纯计算val x: Int get() y 1// 每次读都计算❌同上读别人的字段var x: Int 0; get() field✅setter 隐式用 field必须存var x: Int get() compute(); set(v) { cache v }❌get/set 都没用 field没字段Backing field 属性背后那块真正装数据的私有字段field 是在 getter/setter 内引用它的唯一名字不是所有属性都有 backing field纯计算的属性和被委托的属性都没有。class Demo { // 1. 有 backing field var count: Int 0 set(v) { field if (v 0) 0 else v } // 写入校验 // 2. 无 backing field派生属性 val isPositive: Boolean get() count 0 // 3. 无 backing field转发到别的对象 val displayCount: Int get() count // 每次读 count 的当前值 // 4. 有 backing field默认 getter/setter val id: Long System.currentTimeMillis() }反编译成 Java 后大致是class Demo { private int count; // ← backing field private final long id; // ← backing field // isPositive、displayCount 没有字段只有方法 public int getCount() { return count; } public void setCount(int v) { this.count v 0 ? 0 : v; } public boolean isPositive() { return getCount() 0; } public int getDisplayCount() { return getCount(); } // get()相当于实现了get方法 public long getId() { return id; } }2、委托属性委托属性另一种声明方式例如使用by lazy()创建的属性就是一种委托属性它在第一次访问时才计算其值。val x: Int by lazy { compute() } var y: String by Delegates.observable() { _, old, new - ... } var z: String by map // 委托给 Map用 by 把 get/set 完全交给委托对象此时不能写 get()/set() 自定义块已经被委托接管。