Kotlin新手入坑:空指针检查.|.ST

抓住今天,尽可能少的信赖明天。 喝汤能补 (* ^ ▽ ^ *)

前言

  该文章作为学习交流,如有错误欢迎各位大佬指正 (* ^ ▽ ^ *)

  • 自身技能
    (1)已具备计算机的基本知识
  • 本文简介
    主要讲解:关于null的语法,空值判断的方式,变量延迟初始化的方式,以及kotlin是如何保证空指针安全的。

  如果进行过Android项目开发者,经常会遇到空指针的问题,虽然解决方法不难,但是这个问题经常会导致程序崩溃,对应的到生活中口袋就瘦了。

可空类型系统

  Kotlin默认所有的参数和变量都是不可为空的。当然也提供了一套可空的类型系统。

  • 需要我们在编译时期就将所有潜在的空指针异常处理掉,否则无法编译通过。保证运行时,无空指针的问题。
  • 语法: 在类名的后面加上 ? 。 如:String 不可为空的字符串,String? 可为空null的字符串

上代码

fun main() {
    useFun(null) //直接报红
    useFun1(null) //可以编译通过
}
fun useFun(an: Animal){
    an.eat()
    an.say()
}

fun useFun1(an: Animal?){
    if(an!=null){
        an.eat()
        an.say()
    }
}

判空辅助工具:?.符号、?:符号、!! 符号

  Kotlin提供了一系列的辅助工具,帮助我们轻松处理各种判空情况。

  • 语法 ?.符号 。表示对象不为空时正常调用相应的语法,对象为空则不做任何操作。
    if(an!=null){
	    an.eat()
	    an.say()
    }
    // 可以简写为
    an?.eat()
    an?.say()
  • 语法 ?:操作符。该操作符的左边表达式的结果不为空,就返回左边表达式的结果,否则就返回右边表达式的结果。
    val c = if (a != null){
        a
    }else{
        b
    }
    
   // 将上面代码直接使用?:进行简写
   val  c = a ?: b

项目中,可以简化怎样的代码

fun getTextLength(text : String?) :Int{
    if (text != null){
        return text.length
    }
    return 0
}

// 可以通过 ?.  与  ?: 进行简化
fun getTextLength0(text: String?) = text?.length ?: 0

  Kotlin的空指针检查机制 ,不一定能判断出我们程序所有的非空情况。
如下代码中,逻辑上没有问题,但Kotlin却无法正常编译过,因为geStrLength()函数不知道外部已经进行了为空判断,所以认为str.length的str可能为空。

  • !! 操作符,Kotlin提供的非空断言工具, 在需要的对象后面加上!! ,表示非常确信这里对象不为空,不需要进行空指针检查。

这种方式并不推荐,使用不当就会引发程序问题

val str : String? = "AAA"

fun main() {
    if (str != null){
        geStrLength()
    }
}

fun geStrLength(){
    println(str.length)   // 无法编译通过
    println(str!!.length)
}

let函数–标准函数

let函数,将原始调用对象作为参数传递到Lambda表达式中。

    val obj=""
    obj.let {
        obj2 ->
        //编写具体的业务
    }

  将obj对象传递到lambda表达式中,参数名为obj2,但obj与obj2 是同一个对象。

  • let可以用来处理全局变量为空判断,而if则不行,因为无法保证if语句中的全局变量不被其他线程所修改。

使用let与?.更加简化为空判断

fun useFun1(an: Animal?){
    an?.eat()
    an?.say()
}

// 优化
fun useFun2(an: Animal?){
    an?.let { 
        a ->
        a.say()
        a.eat()
    }
}

// 上篇说的,只有一个参数,可以使用it
    an?.let {
        it.say()
        it.eat()
    }
    
// 无法编译通过

var animal :Animal? = null

fun useFun3(an: Animal?){
    if (animal != null){
        animal.say() //还是报错,animal可能被其他线程修改成null
        animal.eat()
    }
}

**其他标准函数的使用,见常见标准函数 **

变量延迟初始化 lateinit

  在程序中,定义全局变量时,往往会后初始化值,这时就需要将变量初始化为null,而因Kotlin的空指针检查机制,需要对明确知道不可能为空的对象,进行判空处理。所以,提供了延迟初始化的方式对这种问题进行优化。
   延迟初始化:延迟初始化的关键字lateinit ,其作用就是告诉编译器,会在晚些时候对这个变量进行初始化,因此就无需在声明该变量时,就将它赋值为null。

  • 使用延迟初始化后,如果在该对象使用前,未对其进行初始化,程序就会崩溃,并抛出kotlin.UninitializedPropertyAccessException: lateinit property xxx has not been initialized 异常。

  • 判断全局变量是否已经初始化,避免重复初始化的操作。语法是::obj.isInitialized ,如下面代码 ::file.isInitialized。

private lateinit var file: File // 延迟对File类进行初始化
fun main() {
    if (!::file.isInitialized){ // 判断是否已经初始化
        file.exists() 
    }
}

觉得有帮助的点下赞哟,毕竟三连步骤更多,嘻嘻,谢谢大家的支持(* ^ ▽ ^ *)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值