/** * 第 5 章 · Null 安全 — 综合示例 * * 包含: * - 可空类型与非空类型 * - ?. 安全调用 * - ?: Elvis 操作符 * - !! 非空断言(演示其危险性) * - as? 安全转换 * - ?.let { } 链式 * - 集合的可空处理 * - 平台类型陷阱 */ data class Address(val city: String?, val zipcode: String?) data class User(val name: String, val nickname: String?, val address: Address?) fun main() { println("=== 1. 可空 vs 非空 ===") val name: String = "Alice" val nick: String? = null println("name = $name (非空)") println("nick = $nick (可空)") // val s: String = nick // ❌ 编译报错:Type mismatch println("\n=== 2. ?. 安全调用 ===") println("nick?.length = ${nick?.length}") // null println("name?.length = ${name?.length}") // 5 println("\n=== 3. ?: Elvis 默认值 ===") val displayNick = nick ?: "(无昵称)" println("displayNick = $displayNick") val len = nick?.length ?: 0 println("len = $len") println("\n=== 4. !! 危险演示 ===") val safeName: String? = "Bob" println("safeName!!.length = ${safeName!!.length}") // 5 try { val nullName: String? = null println("nullName!!.length = ${nullName!!.length}") } catch (e: NullPointerException) { println("⚠️ 捕获到 NPE: ${e.message ?: "no message"}") println(" → !! 是自杀式操作符,能不用就别用!") } println("\n=== 5. as? 安全转换 ===") val obj: Any = "hello" val asInt: Int? = obj as? Int // null val asString: String? = obj as? String // "hello" println("obj as? Int = $asInt") println("obj as? String = $asString") val n: Int = (obj as? Int) ?: -1 println("用默认值: $n") println("\n=== 6. Smart Cast ===") fun describe(x: Any?) = when { x == null -> "null" x is String -> "字符串,长度 ${x.length}" // 自动当 String 用 x is Int -> "整数,平方 ${x * x}" else -> "其他类型 ${x::class.simpleName}" } listOf(null, "hello", 5, 3.14).forEach { println("${it} → ${describe(it)}") } println("\n=== 7. ?.let { } 链式 ===") val users = listOf( User("Alice", "alice123", Address("Beijing", "100000")), User("Bob", null, Address("Shanghai", null)), User("Charlie", "charlie", null), ) users.forEach { user -> // 老 Java 风格 if (user.address != null && user.address.city != null) { // ↑ 这里 smart cast 不一定成功(开放属性问题),实际可能要本地变量 // println("城市: ${user.address.city}") } // Kotlin 风格 user.address?.city?.let { city -> println("${user.name} 住在 $city") } ?: println("${user.name} 没填城市") } println("\n=== 8. 集合的 null 处理 ===") val mixed: List = listOf("a", null, "b", null, "c") println("原始: $mixed") println("过滤掉 null: ${mixed.filterNotNull()}") println("用空字符串代替 null: ${mixed.map { it ?: "" }}") println("非 null 元素长度之和: ${mixed.sumOf { it?.length ?: 0 }}") println("\n=== 9. requireNotNull / checkNotNull ===") fun process(input: String?) { val name = requireNotNull(input) { "input 不能为空" } println("处理: $name (长度 ${name.length})") } process("hello") try { process(null) } catch (e: IllegalArgumentException) { println("⚠️ 捕获: ${e.message}") } println("\n=== 10. 实战:解析嵌套结构 ===") val u = User("David", null, Address(null, null)) val info = buildString { append("姓名:${u.name}\n") append("昵称:${u.nickname ?: "(未设置)"}\n") append("城市:${u.address?.city ?: "(未填写)"}\n") append("邮编:${u.address?.zipcode ?: "(未填写)"}") } println(info) }