Android---Kotlin 学习004

2023-12-13 08:10:32

null

在 Java 中我们司空见惯的空指针异常 NullPointException,带给了我们很多麻烦。Kotlin 作为更强大的语言,势必会基于以往的语言涉及经验进行改良。Kotlin 更多地把运行时可能出现的 null 问题,以编译时错误的方式,提前在编译期强迫我们重视起来,而不是等到运行时报错。防范于未然,提高了我们程序的健壮性。

可空性

对于 null 值问题,Kotlin 反其道而行之,除非另有规定,变量不可能为 null 值,这样以来,运行时崩溃从根源上得到解决。如下代码

可以发现,上述代码在编译器里就直接报错了,肯定是无法通过编译的。所以,?在 kotlin 中不能给一个变量直接赋空值,除非额外的声明。

null 类型在 kotlin 里仍然存在。只是为了避免 NullPointerException,Kotlin 的做法是不让我们给非空类型变量赋 null 值,但是 null 在 kotlin 中依然存在

可空类型

特殊声明一个可空的类型。在声明变量时加上一个 "String?",特殊声明此变量,表明它是一个可空类型。

null 安全

Kotlin 区分可空类型和非可空类型,所以,你要一个可空类型变量运行,而它又可能不存在,对于这种潜在危险,编译器时刻警惕着。为了应对这种风险,Kotlin 不允许你在可空类型值上调用函数,除非你主动接手安全管理

a) 安全调用操作符

示例:

解释说明:str2 我们声明它是一个可空类型变量,那么编译器就不允许它调用函数。这里我们通过安全调用操作符 “?.”?来手动声明。它的作用就是,当 str2 为空时,就直接跳过调用此函数,所以执行该行代码时就不会报空指针异常。capitalize() 函数把该字符串的首字母变成大写。

如果我们没有使用?“?.”? 那么在编译器就会报错。

b) 使用带 let 的安全调用

安全调用允许在可空类型上调用函数,但是如果还想做点额外的事,比如创建新值,或判断不为 null 就调用其它函数,怎么办?可以使用带 let 函数的安全调用操作符。你可以在任何类型上调用 let 函数,它的主要作用是让你在指定的作用域内定义一个或多个变量

示例:

 fun main() {
    var str = "butterfly"
    str?.let {
        if (it.isNotBlank()){ // str 不为空,则调用capitalize() 函数
            it.capitalize()
        }else{
            // 为空,则 赋值
            "butterfly"
        }
    }
}

解释说明:str 为空类型变量,在它上面执行 let 函数,就可以做更多的操作,比如这里的判断你操作。let 函数返回的是匿名函数最后一行代码执行的结果。这里的 it 指的就是 str。相当于把 str 作为 let 函数的参数传入到了 let 函数里。

c) 非空断言操作符

!!. 又称感叹号操作符,当变量值为 null 时,它会去执行我们的函数,但是它会抛出 NullPointException 异常。

fun main() {
    var str : String? = "hllxy"

    str = null
    println(str2!!.capitalize())
}

?执行上述代码,结果如下

d) 使用 if 判断 null 值情况

示例:

    if(str != null){
        str = str.capitalize()
    }else{
        println("str 为 null.")
    }

但是相比之下安全调用操作符用起来更灵活,代码也更简洁,我们可以用安全操作符进行多个函数的链式调用

示例:

str = str?.capitalize()?.plus(" is great")

e)使用空合并操作符

空合并操作符相当于 java 里简略版的三元表达式。?: 操作符的意思是,如果左边的结果为 null,就使用右边的结果值。

示例:

val strWithSage = str ?: "butterfly"

空合并操作符也可以和 let 函数一起使用来代替 if/else 语句。

示例:

str = str?.let { it.capitalize() } ?: "butterfly"

异常

kotlin 里捕获异常也是通过 try...cache 来完成。

示例:

    var number : Int? = null

    try {
        number!!.plus(1)
    }catch (e : Exception){
        println(e)
    }

这里我们通过?非空断言操作符 !!.?来抛出异常,然后由 cache 捕获。

自定义异常

示例:

import java.lang.Exception

fun main() {
    var number : Int? = null

    try {
        //在 !!. 之前用自定义的异常 来 处理异常
        checkOperation(number)
        number!!.plus(1)
    }catch (e : Exception){
        println(e)
    }
}

// 抛出异常
fun checkOperation(number : Int?){
    // 使用 空合并操作符
    number ?: throw UnskilledException()
}

// 自定义异常
class UnskilledException() : IllegalArgumentException("操作不当")

先决条件函数

Kotlin 标准库提供了一些便利函数,使用这些内置函数,你可以抛出带自定义信息的异常,这些便利函数叫做先决条件函数,你可以用它定义先决条件,条件必须满足,目标代码才能执行。

示例:修改上面自定义异常的?checkOperation() 函数。

// 抛出异常
fun checkOperation(number : Int?){
    // 使用 空合并操作符
    //number ?: throw UnskilledException()
    checkNotNull(number, { "Something is not good!" })
}

其中,checkNotNull 就是先决条件。如果 number 为空,就抛出异常。异常的内容为 {} 里的内容。

文章来源:https://blog.csdn.net/qq_44950283/article/details/134841391
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。