Kotlin笔记:空类型和智能类型转换

2021-03-0311:34:16编程语言入门到精通Comments1,370 views字数 2270阅读模式

空类型

Kotlin 跟 Java 的最大不同应当就属空类型这点了,使用 Kotlin 开发,IDE 会智能的对可能为空的地方进行报错提示,开发者必须处理该错误,否则连编译都通过不了,从而降低程序 NullPointException 异常的出现几率,所以,一般情况下使用 Kotlin 开发很少见到 NPE 异常。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/21003.html

非空与可空类型

fungetName(): String {return"lqr"}

这是一个很普通的函数声明,它指明了函数返回值是一个 String 类型,对此,Kotlin 会认为这是一个不可能返回 null 结果的函数,那如果我就是要返回 null 会怎样?文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/21003.html

fungetName(): String {returnnull}

该 IDE 的报错提示说明了函数返回值类型 String 是一个不能为 null 的值,即非空类型。如果需要函数可以返回 null 的话,需要对函数返回值类型做一点小修改,使其可以用空,这仅仅只需要在返回值类型后面追加 ? 即可:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/21003.html

fungetName(): String?{returnnull}

综上,Kotlin 的类型声明分为两类(包括但不限于函数返回值类型),分别是:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/21003.html

  • 非空类型:单纯声明的类就是非空类型,如:String
  • 可空类型:通过在类后面放置 ? 来声明,如:String?

可空类型操作符

Kotlin 为保证代码空安全,提供了几种处理方式,本节主要陈述其中的 3 种操作符。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/21003.html

了解更多 Kotlin 空安全知识,请访问:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/21003.html

安全调用操作符(?.)

以获取字符串长度为例,非空类型变量直接通过 .length 即可:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/21003.html

val name: String ="lqr"println(name.length)

而可空类型变量,不仅需要在类型声明时使用 ? ,在调用可空类型对象的成员变量 length 时也需要使用 ?. 进行处理:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/21003.html

val name: String?=nullprintln(name?.length)

因为 name 的值为 null,所以 .length 并不会被执行,因此这代码相当于 println(null),虽然结果是 null,但程序并不会崩溃。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/21003.html

安全调用操作符(?.):如果接收者非空,就调用一个方法或访问一个属性,否则不执行。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/21003.html

Elvis 运算符(?:)

日常开发中,我们经常习惯于用一行代码同时处理变量非空或为空的情况,在 Kotlin 中,借助 if-else 代码可以这么写:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/21003.html

println(if(getName()!=null)getName()else"Default Name")

Java 有三元运算符,而 Kotlin 没有,所以这里只能用 if-else文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/21003.html

Kotlin 还提供了 Elvis 运算符(?:),可以对 if-else 进行简化:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/21003.html

println(getName()?:"Default Name")

Elvis 运算符(?:):如果 ?: 左侧表达式非空,elvis 操作符就返回其左侧表达式,否则返回右侧表达式。 请注意,当且仅当左侧为空时,才会对右侧表达式求值。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/21003.html

非空断言运算符(!!)

如果你非常非常确定变量的值绝对不可能为 null,那么你可以在对象调用时使用 !! 对其进行转换成非空类型:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/21003.html

val value: String?="Hello LQR"println(value!!.length)

非空断言运算符(!!):将任何值转换为非空类型,若该值为空则抛出异常。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/21003.html

智能类型转换

类型转换在开发中很常见,特别是在多态的应用情景里,会使用父类变量接收子类对象,并且可能会需要强转成具体的子类类型以使用特定的子类功能。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/21003.html

openclass Parent {}class Child :Parent(){fungetName(): String {return"lqr"}}funmain(args: Array<String>){val man: Parent =Child()println((man as Child).getName())}

Kotlin 里,强转需要使用 as 关键字来处理。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/21003.html

当然了,这里的代码处理的很不好,通常在转换前会先判断对象的具体类型后再做强转,以免出现类型转换异常,因此,代码可以修改为:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/21003.html

val man: Parent =Child()if(man is Child){println(man.getName())}

Kotlin 中使用 is 关键字来判断变量类型,if 代码块中,man 变量已经被识别为 Child 类型了,因此不再需要显式强转,这就是 Kotlin 的智能类型转换,反观 Java 就显的有些笨笨的了:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/21003.html

Parent man =newChild();if(man instanceofChild){
    System.out.println(((Child) man).getName());}

回过头再来看看 as 关键字,Kotlin 代码中使用 as 进行对象的类型强转,如果我们不先进行类型判断,就直接强制变量类型,一旦被强转的对象类型有误,就必定会抛出ClassCastException文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/21003.html

val parent: Parent =Parent()val child: Child = parent as Child
print(child)

还好,Kotlin 的智能类型转换功能为 “直接强转党” 提供了一条出路,那就是使用 as?,同时如果变量有显式指定类型的话,需要将其改为可空类型,或者干脆把变量类型声明去掉:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/21003.html

val parent: Parent =Parent()val child: Child?= parent as? Child
print(child) 

as? 相比 as 要智能一些,当强制类型有误会时,结果会为 null。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/21003.html

  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/ymba/21003.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定