【Kotlin】属性 与 幕后字段 ( 属性声明 | 属性初始化器 | 属性访问器 | field 属性幕后字段 | lateinit 延迟初始化属性 )

简介: 【Kotlin】属性 与 幕后字段 ( 属性声明 | 属性初始化器 | 属性访问器 | field 属性幕后字段 | lateinit 延迟初始化属性 )

文章目录

I . 属性 字段 总结

II . 属性声明

III . 属性初始化器

IV . get / set 属性访问器

V . 属性幕后字段 field

VI . 变量和常量的区别

VII . 延迟初始化属性 lateinit



I . 属性 字段 总结


属性与字段总结 :



① 完整的属性声明格式如下 :


var / val <属性名称>[: <属性类型>] [= <属性初始化器>] 
  [<getter 方法>] 
  [<setter 方法>]


② 属性初始化器 : 就是为属性赋予一个初始值 ;


③ 属性访问器 : 即 属性的 getter 和 setter 方法 ;


④ 属性幕后字段 : 属性的实际值存储在 field 幕后字段中 , 只能在属性访问器中可以使用 field 获取该值 ;


⑤ 延迟加载属性 : 该属性只能是引用类型 , 并且不能有初始化器和访问器 ;




II . 属性声明


1 . 属性声明格式 :


var / val <属性名称>[: <属性类型>] [= <属性初始化器>] 
  [<getter 方法>] 
  [<setter 方法>]


① 属性类型 : 首先设置属性的类型 , 常量 val 或 变量 var ;


② 属性名称 : 必须制定一个属性名称 ;


③ 属性类型 : 属性的类型可以指定 , 也可以在赋值时自动推断属性类型 , 可选设置 ;


④ 属性初始化器 : 给属性一个初始值 , 可选设置 ;


⑤ get 方法 : 获取属性的方法 , 可选设置 ;


⑥ set 方法 : 设置属性的方法 , 可选设置 ;



2 . 属性声明代码示例 : 代码中使用了上述所有的要素 , 除 val 常量外 ;


class Student {
    var age : Int = 18
        //每次访问属性值时 ( 获取属性值 ) , 都会自动调用该 get 方法
        get() {
            println("调用 get 方法")
            return field
        }
        //次为属性赋值时 , 都会调用 set 方法
        set(value) {
            println("调用 set 方法")
            field = value
        }
}




III . 属性初始化器


1 . 属性初始化器概念 : 属性赋值的操作就是属性的初始化器 ;



2 . 属性初始化器的代码优先级 : 属性的初始化器与 init{} 初始化代码块优先级相同 ;



3 . 属性初始化器执行时机 : 在主构造函数调用后 , 会按照类中的代码顺序从上到下执行属性初始化器和 init 初始化代码中的内容 ;




IV . get / set 属性访问器


1 . get 方法 : 属性定义了 get 方法 , 那么每次访问属性值时 ( 获取属性值 ) , 都会自动调用该 get 方法 ;



① 访问器 : get 方法又叫作访问器 , 用于获取属性值 ;


② 属性推断 : 使用 get 方法返回值可以自动推断属性类型 , 这种情况下属性的类型可以省略 ;



2 . set 方法 : 属性定义了 set 方法 , 那么每次为属性赋值时 , 都会调用 set 方法 ;



① 访问器 : set方法也叫作访问器 , 用于设置属性值 ;


② 参数 : set 方法的默认参数是 value , 也可以设置成其它值 ;



3 . 代码示例 : 代码中涉及到了 幕后字段 , 下一小节有详细说明 ;


class Student {
    var age : Int = 18
        //每次访问属性值时 ( 获取属性值 ) , 都会自动调用该 get 方法
        get() {
            println("调用 get 方法")
            return field
        }
        //次为属性赋值时 , 都会调用 set 方法
        set(value) {
            println("调用 set 方法")
            field = value
        }
}
fun main() {
    var student : Student = Student();
    //给 age 属性赋值 , 此时会自动调用其 set 方法
    student.age = 18;
    //获取 age 属性值 , 此时会自动调用其访问器 get 方法
    student.age;
}



执行结果 :


调用 set 方法
调用 get 方法



get 和 set 方法都是属性访问器 , 用于获取或设置属性值




V . 属性幕后字段 field


1 . 属性与字段 :



① 类属性本质 : 类中定义的属性是一系列方法和代码块的集合 , 如 属性初始化器 , 属性访问器 , 属性声明等 , 这不是一个字段 ;


② 没有字段概念 : 在 Kotlin 语言中不能声明字段 , 只能声明属性 , 声明一个属性 , 附带声明了该属性的一系列方法和初始化代码等 ;


③ 幕后字段引入 : 在类中肯定是有一个字段用于存储属性的值 , 这个字段就是幕后字段 , 每个属性都有一个默认的幕后字段 ;



2 . 幕后字段 : 只有在 get / set 属性访问器中才可以使用幕后字段 field , 该字段代表了本属性的属性值 , 类型是属性本身的类型 ;



3 . 幕后字段示例解析 :



下面类中的 get 方法中使用 field 可以获取到 age 属性的 Int 值 ;


在 set 方法中 , 给 field 字段设置值 , 相当于给属性设置了 Int 值 ;


class Student {
    var age : Int = 18
        //每次访问属性值时 ( 获取属性值 ) , 都会自动调用该 get 方法
        get() {
            println("调用 get 方法")
            return field
        }
        //次为属性赋值时 , 都会调用 set 方法
        set(value) {
            println("调用 set 方法")
            field = value
        }
}


4 . 幕后字段产生 : 只有当在属性访问器中使用到了 field 字段后 , 系统才给提供幕后字段 ; 如果在访问器中没有使用 field 字段 , 那么系统就不提供幕后字段 ;




VI . 变量和常量的区别


1 . 修饰符不同 : 变量使用 var 修饰 , 常量使用 val 修饰 ;



2 . 初始化方式不同 :


变量即可以使用 set 初始化 , 也可以使用初始化器进行初始化 ;

常量不允许定义 set 方法 , 只能在初始化器中进行初始化 ;




VII . 延迟初始化属性 lateinit


1 . 修饰引用数据类型 : lateinit 不能修饰基本数据类型 , 只能修饰引用数据类型 , 如下图 , lateinit 修饰 Int 类型 , 报错 'lateinit' modifier is not allowed on properties of primitive types ;

image.png




2 . 属性不能有初始化器 : lateinit 修饰的数据类型不能定义初始化器 , 报错信息 'lateinit' modifier is not allowed on properties with initializer ;

image.png




3 . 属性不能有访问器 : lateinit 修饰的数据类型不能定义 getter 和 setter 属性访问器 ; 报错 'lateinit' modifier is not allowed on properties with a custom getter or setter ;

image.png




4 . 属性定义位置 : 尽量定义在类中 , 1.2 之后的 Kotlin 版本可以定义在主构造函数 和 局部变量中 , 不过为了代码兼容 , 还是在类中定义延迟初始化属性 ;



5 . 延迟初始化属性为空 : 如果在没有初始化属性值时 , 调用该 lateinit 延迟初始化属性 , 会抛出异常 ;



6 . lateinit 延迟初始化属性推荐示例 :


class Student {
    //在类中定义
    //不要定义 属性初始化器
    //不要定义 getter setter 属性访问器
    lateinit var name : String
}


目录
相关文章
|
6天前
|
NoSQL Redis Kotlin
Kotlin - 属性代理
Kotlin - 属性代理
18 5
|
3天前
|
NoSQL Redis Kotlin
Kotlin - 属性代理
Kotlin - 属性代理
10 1
|
9天前
|
NoSQL Redis Kotlin
Kotlin - 属性代理
Kotlin - 属性代理
|
15天前
|
NoSQL Redis Kotlin
Kotlin教程笔记(17) - 属性代理
Kotlin教程笔记(17) - 属性代理
26 1
|
17天前
|
NoSQL Redis Kotlin
Kotlin教程笔记(17) - 属性代理
Kotlin教程笔记(17) - 属性代理
|
22天前
|
NoSQL Redis Kotlin
Kotlin教程笔记(17) - 属性代理
Kotlin教程笔记(17) - 属性代理
24 1
|
23天前
|
NoSQL Redis Kotlin
Kotlin教程笔记(17) - 属性代理
Kotlin教程笔记(17) - 属性代理
22 0
|
1月前
|
JSON 调度 数据库
Android面试之5个Kotlin深度面试题:协程、密封类和高阶函数
本文首发于公众号“AntDream”,欢迎微信搜索“AntDream”或扫描文章底部二维码关注,和我一起每天进步一点点。文章详细解析了Kotlin中的协程、扩展函数、高阶函数、密封类及`inline`和`reified`关键字在Android开发中的应用,帮助读者更好地理解和使用这些特性。
20 1
|
2月前
|
Android开发 开发者 Kotlin
告别AsyncTask:一招教你用Kotlin协程重构Android应用,流畅度飙升的秘密武器
【9月更文挑战第13天】随着Android应用复杂度的增加,有效管理异步任务成为关键。Kotlin协程提供了一种优雅的并发操作处理方式,使异步编程更简单直观。本文通过具体示例介绍如何使用Kotlin协程优化Android应用性能,包括网络数据加载和UI更新。首先需在`build.gradle`中添加coroutines依赖。接着,通过定义挂起函数执行网络请求,并在`ViewModel`中使用`viewModelScope`启动协程,结合`Dispatchers.Main`更新UI,避免内存泄漏。使用协程不仅简化代码,还提升了程序健壮性。
76 1
|
3月前
|
调度 Android开发 开发者
【颠覆传统!】Kotlin协程魔法:解锁Android应用极速体验,带你领略多线程优化的无限魅力!
【8月更文挑战第12天】多线程对现代Android应用至关重要,能显著提升性能与体验。本文探讨Kotlin中的高效多线程实践。首先,理解主线程(UI线程)的角色,避免阻塞它。Kotlin协程作为轻量级线程,简化异步编程。示例展示了如何使用`kotlinx.coroutines`库创建协程,执行后台任务而不影响UI。此外,通过协程与Retrofit结合,实现了网络数据的异步加载,并安全地更新UI。协程不仅提高代码可读性,还能确保程序高效运行,不阻塞主线程,是构建高性能Android应用的关键。
61 4