?. !!. ?.let和?: 的区别

本文详细介绍了Kotlin中的空安全特性,包括可空类型与非空类型的使用区别,以及?.和!!.操作符的功能与适用场景。此外,还探讨了let语句和Elvis操作符?:如何简化对可空对象的访问与处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、? 与 !! 的比较
val a: String = "aa"
    /*
    * a是非空类型,下面的给a赋值为null将会编译不通过
    * */
    // a = null
    a.length

    /*
    * ?声明是可空类型,可以赋值为null
    * */
    var b: String? = "bb"
    b = null
    
    /*
    * b是可空类型,直接访问可空类型将编译不通过,需要通过?.或者!!.来访问
    * */
    // b.length
    b?.length
    b!!.length
  • 对于一个不可为空类型:如果直接给不可为空类型赋值一个可能为空的对象就在编译阶段就不能通过
  • 对于一个可空类型:通过?声明,在访问该类型的时候直接访问不能编译通过,需要通过?.或者!!.
    • ?. 代表着如果该类型为空的话就返回null不做后续的操作,如果不为空的话才会去访问对应的方法或者属性
    • !!. 代表着如果该类型为空的话就抛出NullPointerException,如果不为空就去访问对应的方法或者属性, 所以只有在很少的特定场景才用这种符号,代表着程序不处理这种异常的case了,会像java代码一样抛出NullPointerException。 而且代码中一定不用出现下面这种代码,会让代码可读性很差而且如果有空指针异常,我们也不能马上发现是哪空了:
    /*
    * 不推荐这样的写法:链式的连续用!!.
    * */
    val user = User()
    user!!.name!!.subSequence(0,5)!!.length

二、let语句简化对可空对象对访问

  • let函数默认当前这个对象作为闭包的it参数,返回值是函数里面最后一行,或者指定return。
 * 通过let语句,在?.let之后,如果为空不会有任何操作,只有在非空的时候才会执行let之后的操作
    * */
    user?.let {
        it.name
        it.age
        it.toString()
    }


三、?: 简化对空值的处理

?:符号会在符号左边为空的情况才会进行下面的处理,不为空则不会有任何操作。跟?.let正好相反,例如我们可以用两行代码来简化上面从操作:

/**
 * Elvis操作符 ?: 简化对空值的处理
 */
fun testElvis2(input: String?, user: User?) {
    val b = input?.length ?: -1;
    user?.save() ?: User().save()
}





### ArkTs 中可空操作符 `??` `?.` 的含义及用法 在 ArkTs 中,`??` `?.` 是两种重要的操作符,用于处理可能为空(`null` 或 `undefined`)的值或对象属性。以下是它们的具体含义用法: #### 1. 空值合并操作符 `??` 空值合并操作符 `??` 主要用于处理可能为 `null` 或 `undefined` 的值。它会在左操作数为 `null` 或 `undefined` 时返回右操作数,否则返回左操作数[^1]。 - **语法**: ```typescript leftValue ?? rightValue ``` - **示例**: ```typescript let a: number | null = 0; let b = a ?? 10; // 输出 0,因为 0 不是 null 或 undefined console.log(b); // 0 let c: string | null = null; let d = c ?? "default"; // 输出 "default",因为 c 是 null console.log(d); // "default" let e: string | undefined = undefined; let f = e ?? "default"; // 输出 "default",因为 e 是 undefined console.log(f); // "default" ``` #### 2. 可选链操作符 `?.` 可选链操作符 `?.` 用于安全地访问对象的嵌套属性或调用方法。当链中的某个部分为 `null` 或 `undefined` 时,表达式会短路并返回 `undefined`,而不会抛出错误[^2]。 - **语法**: ```typescript object?.property object?.[expression] function?.(arguments) ``` - **示例**: ```typescript const user = { name: "Alice", address: { city: "Beijing" } }; // 正常访问 console.log(user?.address?.city); // 输出 "Beijing" // 如果中间某层为 null 或 undefined,则返回 undefined console.log(user?.contact?.phone); // 输出 undefined,因为 contact 不存在 // 函数调用 const obj = { greet: () => "Hello" }; console.log(obj?.greet?.()); // 输出 "Hello" console.log(obj?.sayHi?.()); // 输出 undefined,因为 sayHi 不存在 ``` #### 3. 区别与联系 - **区别**: - `??` 用于处理两个值之间的逻辑关系,当左操作数为 `null` 或 `undefined` 时返回右操作数。 - `?.` 用于安全地访问对象的属性或调用方法,避免因 `null` 或 `undefined` 导致的运行时错误。 - **联系**: - 两者都与 `null` `undefined` 相关,但作用范围不同。`??` 更关注值的替代,而 `?.` 更关注对象结构的安全访问。 #### 4. 注意事项 - 在使用 `??` 时需要注意,只有当左操作数严格等于 `null` 或 `undefined` 时才会触发替代逻辑。例如,`0`、`false` 空字符串 `""` 都会被视为有效值[^1]。 - 在使用 `?.` 时,如果链中某一层为 `null` 或 `undefined`,则后续的所有访问都会停止,并返回 `undefined`。 ```typescript let value1 = null ?? "default"; // "default" let value2 = undefined ?? "default"; // "default" let value3 = 0 ?? "default"; // 0 let value4 = false ?? "default"; // false let value5 = "" ?? "default"; // "" const obj = { a: { b: null } }; console.log(obj?.a?.b); // null console.log(obj?.a?.c); // undefined ``` ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值