Kotlin基础六

本文详细介绍了Kotlin中处理空类型的各种方法,包括安全调用运算符、猫王运算符、安全类型转换、非空断言等。同时,还探讨了let函数、延迟初始化属性、可空类型的扩展函数等内容。

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

内容:

  • Kotiin对可空类型的显式的支持
  • 可空类型的安全调用运算符
  • 猫王运算符

  • 安全类型转换

  • 非空断言

  • let函数

  • 延迟初始化的属性

  • 可空类型的扩展函数

  • 不用问号结尾,类型参数也能是可空的

  • 平台类型

一可空类型必须显式支持

 在java编写的代码的时候我们经常回碰到空指针异常的问题,kotlin为了减少和杜绝这种错的发生,提供了必须显示当前类型是否可以为null。默认全部不能为null

我们看下边一段java代码:

#java
public int getlength(String str){
    return str.length();
}复制代码

这个函数在被调用的时候有可能会抛空指针异常,因为你控制不了外部传入的数据是否为null。

而对于Kotlin中去编写同样一段这样的代码,你必须指明当前传入的参数是否允许为null。

如果要求不能传入null,你必须这样写:

#kotlin
fun getlength(str: String): Int {
    return str.length
}复制代码

如果要求可以传入null,你必须这样写:

fun getlength(str: String?): Int {
    return str.length//先忽略这行
}复制代码
显式地在类型名称后面加上问号来标记它,标记可以传入null值。问号可以加在任何类型的后边,包括自定义类型。

如果你有一个可空的值,你操作他们都会受到限制,例如:

1.可空类型不能直接调用他的方法:

上边传入字符串可null,调用方法str.length就会报错复制代码

2.不能把可空类型的值传给拥有非空类型参数的函数

#错误代码
val str:String? = "我可能为null"
var str2:String = str复制代码

怎么样能解除这些限制呢?

因为上边错误代码,在开发中是非常常见的写法。

解决:和null比较,在这次比较的作用域中编译器都是把它看成非null看待。

fun getlength(str: String?): Int {
    return if (str != null) str.length else 0
}复制代码

这种解决方法比java的代码还要啰嗦,kotlin提供了一些工具来帮助我们用更简洁的方式来处理可空值。

二 可空类型安全调用运算符?.

他是把可空类型检查和调用合并在一起使用:

val str: String? = "我可能为null"
str?.length复制代码

这个调用的代码等同于

if (str!=null) str.length else null复制代码

注意:这次安全调用的结果有可能也是null,如

fun getlength(str: String?): Int? {
    return str?.length
}复制代码

返回值有可能为null,所以返回值也是可null类型。

它不仅可以安全调用方法,还可以安全调用属性如:

class Book(val name :String , val author :List<String>?)复制代码
val book = Book("小三上位", null)
book.author?.size复制代码

且安全调用可以在一个表达式中连续使用。如下代码:

class Person(val name:String ,val company :Company?){
    
    fun getCity():String{
         val str = company?.address?.city
        return  if (str!=null) str else "UnKnow"
    }

}复制代码
class Company(val name :String, val address :Address?)复制代码
class Address(val city :String)复制代码

可以看到上边的Person类里边连续使用了安全调用属性,且代码最后用if去判断是否是null,来处理是null的情况。

那么我们能把这里的非空判断去掉吗?

需要引入一个新的运算符 ?:

三 猫王运算符 ?:

修改上边person类变成这样

class Person(val name: String, val company: Company?) {

    fun getCity(): String {
        return company?.address?.city ?: ""
    }
}复制代码

写法: 运算数1?: 运算数2

如果运算数1不为null,运算结果就是运算数1;如果运算数1为null,运算结果就是运算数2。

四安全类型转换 as?

我们在第一篇文章中知道使用is关键字去判断一个类型属于另外一个类型,如果是,他会自动转换。并且还知道可以使用as关键字去显示的转换一个类型到另外一个类型。

注意:假如我们没有判断一个类型属于不属于另外一个类型,而是直接as类型转换,这个时候如果是这个类型没有问题,如果不是这个类型,直接都会报类型转换异常的错误。

对于这个问题kotlin给出了安全类型转换

open class Father复制代码
class Son复制代码
val son = Son()
val iss = son as? Father复制代码

这个时候就不会报类型转换异常,而对应的返回的iss就是一个null类型。

我们常常回结合猫王运算符一起使用:

val iss = son as? Father?: false复制代码

这样再很多场景都可以用到类似这样的表达式

fun aaa(o: Any?): Boolean {
    这里如果不是这个类型,直接返回false,如果是这个类型,下边就可以用这个类型的方法
    val bbb = o as? Son ?: return false

    return bbb.name=="张三"

}复制代码

五 非空断言

非空断言是Kotlin提供给你的最简单直率的处理可空类型值的工具,就是告诉编译器,我知道这个值不为null,如果我错了我准备好了接收这个异常。如
val str :String? = ""
val str2 =  str!! 
str2.length复制代码

这里对str做了非空断言,如果为null,就会直接抛空指针异常的错误。抛异常的是断言的那行代码。

六let函数

我们在实际开发中常常遇到这样一种情况,调用这个函数是允许传递null值的,但是我们要传递的确实一个可空参数,像这样:

fun sentEmall(email: String){

}复制代码

调用:

val str: String? = "xxxx@qq.com"
if (str != null)
    sentEmall(str)复制代码

这里需要加上一个非空的判断,Kotlin给我们提供另外一种处理方式:使用let函数

str?.let { sentEmall(it) }复制代码

这里使用要传递的参数调用let函数,里边传递一个表达式,如果str不为null,就后调用sentEmall方法,且it就是这个str的非空,如果str为null,就不会调用sentEmall方法。

注意let方法可以嵌套调用,像这样:

fun sentEmall(address: String ,content:String) {


}复制代码
val str1: String? = "xxxx@qq.com"
val str2: String? = "xxxx@qq.com"
str1?.let { it->str2?.let { sentEmall(str1,str2) } }复制代码

七延迟初始化的属性

Kotiin通常要求你在构造方法中初始化所有属性,如果某个属性是非空类型,你就必须提供非空的初始化值。否则,你就必须使用可空类型。如果你这样做,该属性的每一次访问都需null检查或者!!运算符。

这不就扯淡了嘛!

但是kotlin为我们提供了延迟初始化来解决这个问题。类似这样:

lateinit var  string :String复制代码
注意,延迟初始化的属性都是var,因为需要在构造方法外修改它的值,而val属性会被编译成必须在构造方法中初始化的final字段。尽管这个属性是非空类型,但是你不需要在构造方法中初始化它。如果在属性被初始化之前就访问了它,直接抛出异常。

八可空类型的扩展函数

我们在java中一定没有用null值去调用过一个函数,而在kotlin中可以使用null去调用两个函数,而且不用安全调用,这两个函数分别是:isNullOrEmpty(),isNullOrBlank(),他们是null类型的扩展函数,isNullOrEmpty()是判断是否是null或者空字符串,isNullOrBlank是判断是否是null或者空格字符串。

但是我们上边提到一个let函数,他必须安全调用,否则会报错。因为他并不是检查调用者是否为null。

九不用问号结尾,类型参数也能是可空的。

Kotiin中所有泛型类和泛型函数的类型参数默认都是可空的,因为默认情况下在编译的时候把泛型推导成了Any?  如下:

fun <T> aaaa(t: T) {
    t?.hashCode()
}复制代码

如果不想要泛型是可空的,我们需要指定类型,像这样:

fun <T:Any> aaaa(t: T) {
    t.hashCode()
}复制代码

十 平台类型

java中的变量在kotlin中既可以当成可空类型,也可以当成非可空类型去处理,而且不会提示到底是不是null,这个需要你自己去判断是否为null。这就是所谓的转化成平台类型。平台类型在kotlin中不能声明,该类型只能来至java中。

小结

  1. Kotlin中需要显示的表现出可空类型,用?加到类型后边
  2. Kotlin中对于可空类型,需要安全调用,不管是方法还是属性,用?.去调用,如果是null,整个表达式就会返回null
  3. Kotlin中对猫王操作符,需要使用 左边?:右边,如果左边是null,直接返回右边。
  4. 安全转换 as?防止出现类型异常转换错误
  5. 非空断言,!! 简单除暴告诉编译器,他不是null
  6. let函数开发中非空和可空的麻烦问题,可嵌套使用
  7. 延迟初始化,可在构造方法外初始化,如果未初始化就使用,会报错
  8. 可空类型扩展的两个方法介绍
  9. 不使用?,类型也可能为null的特殊情况
  10. 平台类型既可以是可空又可以为非空


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值