- 可空性
// TODO 第一种情况:默认是不可空类型,不能随意给null
var name: String = "KK"
// 提示:不能是非空类型String的值
// name = null
println(name)
// TODO 第二种情况:声明时指定为可空类型
var name2: String ?
name2 = null
println(name2)
- 安全调用操作符
var name: String? = "zhangsan"
// name = null
// name.capitalize() // name是可空类型的 可能是null,想要使用name,必须给出补救措施
val r = name?.capitalize() // name是可空类型的 如果真的是null,?后面这一段代码不执行,就不会引发空指针异常
println(r)
- let的安全调用
var name: String? = null
name = "Derry"
name = ""
// name是可空类型的 如果真的是null,?后面这一段代码不执行,就不会引发空指针异常
val r =name?.let {
// it == name 本身
// 如果能够执行到这里面的,it 一定不为null
if (it.isBlank()) { // 如果name是空值 "" 没有内容
"Default"
} else {
"[$it]"
}
}
println(r)
- 非空断言操作符
var name: String? = null
// name.capitalize() // name是可空类型的 可能是null,想要使用name,必须给出补救措施
// name = "derry"
// 补救措施 我们已经学习了 ?
val r = name!!.capitalize() // !! 断言 不管name是不是null,都执行,这个和java一样了
println(r)
// 结论:规矩:如果百分百能够保证name是有值的,那么才能使用断言 !!, 否则有Java 空指针异常的风险
- 空合并操作符
var info: String? = "李小龙"
// info = null
// 空合并操作符 xxx ?: "原来你是null啊" "如果xxx等于null,就会执行 ?: 后面的区域"
println( info ?: "原来你是null啊" )
// let函数 + 空合并操作符
println(info?.let { "【$it】" } ?: "原来你是null啊2")
- 先决条件函数
var value1: String ? = null
var value2: Boolean = false
// checkNotNull(value1) // java.lang.IllegalStateException: Required value was null.
// requireNotNull(value1) // java.lang.IllegalArgumentException: Required value was null.
require(value2) // java.lang.IllegalArgumentException: Failed requirement.
设计意图:
明确契约
这些函数用于在代码中标记不可违反的条件(如参数校验、状态检查),一旦违反即说明程序逻辑存在严重错误,继续执行可能导致更隐蔽的 Bug 或数据污染。
快速暴露问题
在开发/测试阶段立即崩溃,比生产环境中产生不可预测的行为更安全。
- substring
//和Java相同,多了until 这种语法糖
INFO.substring(0 until indexOf)
- 解构
val jsonText = "AA,BB,CC,DD"
// list 自动类型推断成 list == List<String>
val list = jsonText.split(",")
// 直接输出 list 集合,不解构
println("分割后的list里面的元素有:$list")
// C++ 解构 Kt也有解构
val (v1, v2, v3, v4) = list
println("解构四个只读变量的值是:v1:$v1, v2:$v2, v3:$v3, v4:$v4")
== 与 ===比较操作
== 是内容的比较
=== 是引用的比较字符串遍历操作
val str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
str.forEach { c -> // 覆盖默认的it参数名,修改参数名为 c
// it == str的每一个字符 A B C D ...
// print("所有的字符是:$it ")
print("所有的字符是:$c ")
}
- 安全转换函数
val number: Int = "666".toInt()
println(number)
// 解决什么奔溃的问题
val number2: Int? = "666.6".toIntOrNull()
println(number2)
val number3: Int? = "888".toIntOrNull()
println(number3)
val number4: Int? = "888.8".toIntOrNull()
println(number4 ?: "原来你是null啊")
- Double转Int与类型格式化
println(65.4645654.toInt()) // 65 四舍五入
println(65.4645654.roundToInt()) // 65 四舍五入
println(65.8343433.roundToInt()) // 66 四舍五入
// 结论:用 roundToInt()函数,保证 Double ->转Int 持有四舍五入的效果
// r的类型: String
val r = "%.3f".format(65.8343433)
println(r)
- 五大内置函数
- takeIf
name.takeIf { true/false } true:返回name本身,false返回null
- takeUnless
name.takeUnless { true/false } false:返回name本身,true返回null