博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Kotlin基础六
阅读量:7210 次
发布时间:2019-06-29

本文共 4414 字,大约阅读时间需要 14 分钟。

内容:

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

  • 安全类型转换

  • 非空断言

  • let函数

  • 延迟初始化的属性

  • 可空类型的扩展函数

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

  • 平台类型

一可空类型必须显式支持

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

我们看下边一段java代码:

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

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

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

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

#kotlinfun 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
?)复制代码
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 
aaaa(t: T) { t?.hashCode()}复制代码

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

fun 
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. 平台类型既可以是可空又可以为非空

转载地址:http://vzgum.baihongyu.com/

你可能感兴趣的文章
大厂的 Android 应用都在用开源框架
查看>>
git学习之git reflog和git cherry-pick
查看>>
福利: 由浅入深的 Web Server 免费电子书
查看>>
R.swift-优雅地引用项目资源
查看>>
Echarts单独对Y轴单位进行文本样式修改
查看>>
EBank 电子银行发布 2.1.0 版本
查看>>
广州区块链公司-前端开发(node全栈)
查看>>
HTML标签样式初始化
查看>>
Vue代码模块定位插件vue-component-finder介绍
查看>>
vue 由0到1实现
查看>>
vue.js实现原理 -- 订阅者,发布者模式
查看>>
填坑-十万个为什么?(19)
查看>>
vue 使用svg图片 svg-sprite-loader
查看>>
idea实用插件
查看>>
iOS应用签名(下)
查看>>
【译】ObjectBox官方文档(6)——ObjectBox与Kotlin
查看>>
深入学习Activity生命周期
查看>>
168 Excel Sheet Column Title
查看>>
HTML学习--空元素
查看>>
未来三年人工智能将融入日常生活
查看>>