主要内容
- 1、初始化代码块
- 2、次构造初始化顺序
- 3、延迟初始化 lateinit
- 4、惰性初始化 by lazy
1、初始化代码块
- init 不是Java的 static{}
- init 相当于Java的 {}
- 在init 中 可以调用主构造函数中的临时类型,进行一些校验工作
代码格式
init {
//......
}
实例:
class KotlinInitialize(_name: String, _age: Int, _sex: Char) {
val name=_name
//这个不是Java的 static{}
//相当于Java的 {}
//可以调用主构造函数中的临时类型,进行一些校验工作
init {
println("init被调用 name=$_name,age=$_age,sex=$_sex")
//对输入的年龄进行校验
require(_age>0){"你的年龄不符合要求"}
}
constructor(name: String) : this(name, 88, 'M') {
println("次构造被调用 name=$name")
}
}
fun main() {
KotlinInitialize("Kotlin",88,'M')
println()
KotlinInitialize("C++")
println()
KotlinInitialize("Java",-1,'W')
}
输出:当不符合检验要求是直接报错
init被调用 name=Kotlin,age=88,sex=M
init被调用 name=C++,age=88,sex=M
次构造被调用 name=C++
init被调用 name=Java,age=-1,sex=W
Exception in thread "main" java.lang.IllegalArgumentException: 你的年龄不符合要求
at com.example.mykotlin2.classs.KotlinInitialize.<init>(KotlinInitialize.kt:12)
at com.example.mykotlin2.classs.KotlinInitializeKt.main(KotlinInitialize.kt:28)
at com.example.mykotlin2.classs.KotlinInitializeKt.main(KotlinInitialize.kt)
2、次构造初始化顺序
//第一步:主构造调用
class KotlinInitialize(_name: String, _age: Int, _sex: Char) {
//第二步:成员属性初始化
val name = _name
//可以调用主构造函数中的临时类型,进行一些校验工作
init {
//第三步:初始化代码块调用
println("init被调用 name=$_name,age=$_age,sex=$_sex")
require(_age > 0) { "你的年龄不符合要求" }
}
constructor(name: String) : this(name, 88, 'M') {
//第五步:次构造函数调用
println("次构造被调用 name=$name")
}
//第四部:成员属性初始化
val info = "初始化顺序信息"
}
由上面实例说明次构造函数初始化顺序:
- 第一步:调用主构造
- 第二步:调用 init之前的成员属性初始化
- 第三步:初始化代码块调用
- 第四步:调用 init之后的成员属性初始化
- 第五步:调用次构造函数
3、延迟初始化 lateinit
延时初始化属性用 lateinit 关键之进行申明
lateinit var requestInfo: String
模拟一个加载数据实例:
注意:调用延时加载属性是必须确保已经初始化了,否则会直接崩溃
可以通过 isInitialized 进行判断是否初始化,进行容错处理
class KotlinLateInit {
lateinit var requestInfo: String
fun loadRequest() {
requestInfo = "加载数据成功"
}
//调用延时加载属性是必须确保已经初始化了,否则会直接崩溃
fun showRequestInfo() {
//这里进行一个初始化判断防止出现崩溃
if (::requestInfo.isInitialized) {
println("当前加载信息requestInfo=$requestInfo")
} else {
println("当前还未初始化")
}
}
}
fun main() {
val kotlinLateInit = KotlinLateInit()
kotlinLateInit.showRequestInfo()
println()
println("手动调用初始化后再调用显示")
kotlinLateInit.loadRequest()
kotlinLateInit.showRequestInfo()
}
输出:
当前还未初始化
手动调用初始化后再调用显示
当前加载信息requestInfo=加载数据成功
4、惰性初始化 by lazy
惰性初始化相当于懒汉式单例模式一样,只有使用到的时候才初始化,用 by lazy
采用普通加载方式与惰性初始化进行比较
class KotlinLazy {
//使用普通方式加载数据
val data = readDataAction()
//使用惰性初始化加载数据
val dataLazy by lazy { readDataAction() }
fun readDataAction(): String {
println("开始读取数据......")
println("加载读取数据......")
println("加载读取数据......")
println("加载读取数据......")
println("加载读取数据......")
println("加载读取数据......")
println("加载读取数据......")
println("加载读取数据......")
println("结束读取数据......")
return "data read finish"
}
}
fun main() {
//对象一创建,data 就已经把数据加载完了
val kotlinLazy = KotlinLazy()
println()
Thread.sleep(3000)
println("开始惰性加载")
println(kotlinLazy.dataLazy)
}
输出:
开始读取数据......
加载读取数据......
加载读取数据......
加载读取数据......
加载读取数据......
加载读取数据......
加载读取数据......
加载读取数据......
结束读取数据......
开始惰性加载
开始读取数据......
加载读取数据......
加载读取数据......
加载读取数据......
加载读取数据......
加载读取数据......
加载读取数据......
加载读取数据......
结束读取数据......
data read finish
根据实例可知,只要 KotlinLazy() 对象一创建,data 就已经把数据加载玩了,而 dataLazy 只有在调用的时候才出发了打印