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 替代属性名以避免递归。
相关推荐
程序员陆业聪19 小时前
绕过Frida/Xposed的最后防线:SVC直接系统调用与Native反Hook实战
android
程序员陆业聪20 小时前
WebView与原生JS交互:JSBridge生产级实现与安全防护
android
我命由我123451 天前
Android 开发问题:MlKitException: An internal error occurred during initialization.
android·java·java-ee·android jetpack·android-studio·androidx·android runtime
Meteors.1 天前
Android自定义 View 三核心方法详解
android
2501_916007471 天前
前端开发常用软件与工具全面指南
android·ios·小程序·https·uni-app·iphone·webview
赏金术士1 天前
Android Tinker 热修复集成与使用指南 1.9.15.2
android·热修复·tinker
2603_954138391 天前
安卓误删文件先别慌!5个实用小技巧指南教你补救
android·智能手机
波诺波1 天前
5-SOFA可变形的3D物体 5-elasticity.scn
android
2501_915909061 天前
iOS应用性能优化:十大策略提升用户体验与开发效率
android·ios·小程序·https·uni-app·iphone·webview
sun0077001 天前
打通android全链路,网卡驱动, 内核 , 到上层hal, framework
android