Kotlin 定义类与field关键

在 Kotlin 中,类的属性与 field 关键字的使用是语法设计中的重要特性。以下是详细解析:


一、Kotlin 类的定义

Kotlin 通过 class 关键字定义类,属性默认自动生成 getter/setter

kotlin 复制代码
class Person {
    var name: String = "默认值" // 自动生成 getter 和 setter
    val age: Int = 0          // 只读属性,仅生成 getter
}

二、field 关键字的作用

field 是 Kotlin 中用于访问属性‌幕后字段 ‌(backing field)的关键字,仅在属性的 get()set() 自定义逻辑中使用。

1. ‌**隐式使用 field**‌

默认情况下,Kotlin 会自动为属性生成幕后字段:

csharp 复制代码
var counter = 0
    // 等价于以下隐式代码:
    // get() = field
    // set(value) { field = value }

2. ‌**显式使用 field**‌

当自定义 get()set() 时,必须通过 field 访问实际存储值:

javascript 复制代码
var name: String = ""
    get() = field.uppercase()  // 返回大写值,但不修改存储值
    set(value) {
        field = value.trim()   // 赋值前去除首尾空格
    }

三、使用 field 的注意事项

1. ‌避免递归调用

直接使用属性名会触发 getter/setter,导致递归:

javascript 复制代码
// ❌ 错误示例:导致栈溢出
var counter = 0
    set(value) {
        if (value >= 0) this.counter = value // 递归调用 set()
    }

// ✅ 正确写法:使用 field
var counter = 0
    set(value) {
        if (value >= 0) field = value
    }

2. ‌仅限在 get()/set() 中使用

field 不可在类其他方法中直接访问:

kotlin 复制代码
class Demo {
    var data = 0
    
    fun update() {
        field = 10 // ❌ 编译错误:field 只能在 getter/setter 中使用
    }
}

四、无幕后字段的场景

如果属性不依赖幕后字段存储数据(例如通过计算获得值),则无需使用 field

kotlin 复制代码
val isAdult: Boolean
    get() = age >= 18  // 直接依赖其他属性,无需 field
    
    
 
// 计算属性  下面这样写 get函数覆盖了 field 内容本身,相当于field失效了,无用了,以后用不到了
var number2 : Int = 0
    get() = (1..1000).shuffled().first() // 从1到1000取出随机值 返回给 getNumber2()函数
/*
    背后隐式代码:
    为什么没有看到 number2 属性定义?
    答:因为属于 计算属性 的功能,根本在getNumber2函数里面,就没有用到 number2属性,所以 number2属性 失效了,无用了,以后用不到了

     public int getNumber2() {
        return (1..1000).shuffled().first()java的随机逻辑 复杂 ;
   }
 */

五、与 Java 的对比

特性 Java Kotlin
字段定义 显式声明为 private 字段 自动生成幕后字段,通过 field 访问
访问控制 手动实现 getter/setter 默认自动生成,可自定义逻辑
属性访问 直接访问字段或调用方法 统一通过属性名访问,隐藏底层实现

六、完整示例

ini 复制代码
class KtBase69 {

var name = "Derry"
    get() = field
    set(value) {
        field = value
    }
/* 背后做的事情:

   @NotNull
   private String name = "Lili";

   public void setName( @NotNull String name) {
        this.name = name;
   }

   @NotNull
   public String getName() {
        return this.name;
   }

 */

var value = "ABCDEFG"
    // 下面的隐式代码,不写也有,就是下面这个样子
    get() = field
    set(value) {
        field = value
    }

var info = "abcdefg ok is success"
    get() = field.capitalize() // 把首字母修改成大写
    set(value) {
        field = "**【$value】**"
    }
    

/* 背后做的事情:
    @NotNull
    private String info = "abcdefg ok is success";

    public void setInfo( @NotNull String info) {
        this.info = "**【" + info + "】**";
    }

    @NotNull
    public String getInfo() {
        return StringKt.capitalize(this.info)
    }

 */


}

class User {

    var email: String = ""
        set(value) {
            field = if (value.contains("@")) value else "invalid"
        }

    val info: String
        get() = "Email: $email"
}

//Kotlin 定义类与field关键
fun main(){

    // 背后隐式代码:new KtBase69().setName("wangwu");
    val ktBase69 = KtBase69()
    ktBase69.name = "wangwu"
    
    println(ktBase69.name)
    println("value:${ktBase69.value}")
    println("info: ${ktBase69.info}")

    val user = User()
    user.email = "test"  // 自动调用 setter,赋值 "invalid"
    println(user.info)
}

七、总结

  • ‌**field 的作用**‌:在自定义 get()/set() 中访问属性的实际存储值。
  • 使用场景‌:需要控制属性读写逻辑时(如数据校验、格式化)。
  • 避免错误 ‌:在自定义访问器中,始终用 field 替代属性名以避免递归。
相关推荐
pengyu6 小时前
【Kotlin 协程修仙录 · 金丹境 · 初阶】 | 并发艺术:async/await 与并发组合的优雅之道
android·kotlin
沐言人生7 小时前
ReactNative 源码分析3——ReactActivity之初始化RN应用
android·react native
YaBingSec8 小时前
网络安全靶场WP:Grafana 任意文件读取漏洞(CVE-2021-43798)
android·笔记·安全·web安全·ssh·grafana
YF02118 小时前
彻底解决Android非SDK接口绕过限制的深度实践
android·google·app
IVEN_8 小时前
Gradle 依赖下载 403 Forbidden 修复:全局镜像配置实战
android·后端
恋猫de小郭9 小时前
Flutter 3.44 发布前夕,官方宣布 SwiftPM 将完全取代 CocoaPods
android·前端·flutter
黄林晴9 小时前
重磅发布!KMP 双端订阅支付彻底封神,一套代码搞定 iOS+Android
android·kotlin
Carson带你学Android9 小时前
别再乱学了!深度解读 Google 官方发布 Android 6 大核心 Skills
android·前端·ai编程
张风捷特烈9 小时前
状态管理大乱斗#06 | Riverpod 源码评析 (下) - 外功心法
android·前端·flutter
三少爷的鞋10 小时前
Kotlin 协程 vs Java 虚拟线程:两种并发模型的对比
android