<font face= 黑体>在 Kotlin 中的类与接口 中咱们已经讲了 Kotlin 的 类、接口 和 扩展方法,今天咱们来说 Kotlin 中的 空类型安全 和 智能类型转换。java
<font face= 黑体>Java 语言中是没有空类型安全这一律念的,因此写 Java 代码常常会出现空指针异常,可是 Kotlin 致力于消除空引用所带来的危险,因此就有了空类型安全概念。git
<font face= 黑体>下面这段代码在 Kotlin 中是没法编译经过的,由于 Kotlin 的 String 是不能接受空值的,因此这个赋值操做是不被容许的。github
var nonNull: String = "Hello" nonNull = null // 不可空类型,不能赋值为 null // 访问长度的话,不须要空判断 val length = nonNull.length
<font face= 黑体>IDE 报错以下所示:segmentfault
<font face= 黑体>可是若是咱们非得定义一个空值,也是有办法的,Kotlin 为了 100% 兼容 Java,必须得实现接收空值,因此要接收空值能够在定义的时候加一个 ?。安全
<font face= 黑体>可是这个时候这个变量就多是空值,因此访问的时候就会比较严格,好比下面代码中的 nullable.length 就会报错,由于可能触发空指针异常。函数
var nullable: String? = "Hello" nullable = null // 可空类型,编译经过 val length = nullable.length // 可能触发空指针,编译保报错
<font face= 黑体>IDE 报错以下所示:
<font face= 黑体>这个时候咱们想 nullable.length 不报错能够:this
<font face= 黑体>当咱们肯定 nullable 不可能为空的时候,能够将 nullable 强转为不可空类型,以下所示:spa
var nullable: String? = "Hello" // 不会报错了(本身已经知道了,这个 nullable 不可能为空) val length = nullable!!.length
<font face= 黑体>若是咱们不肯定 nullable 是否为空的时候,能够用 ?. 来实现安全访问,以下所示:线程
var nullable: String? = "Hello" // 这种状况下若是 nullable 为空的话,那么返回的 length 也是空 val length = nullable?.length // 这时候 length 的类型不是 Int,而是 Int?,因此能够写成下面这样 val length: Int? = nullable?.length // 若是你想 length 的类型是 Int 的话,能够加个默认值,写成下面这样 val length: Int = nullable?.length ?: 0 // 若是 nullable?.length 为空, 就返回0
<font face= 黑体>咱们知道 Int 是 Number 的子类,因此经过下面的代码咱们就能够知道 String 应该是 String? 的子类。
var a: Int = 2 var b: Number = 10.0 a = b // Type mismatch,报错 b = a // OK var x: String = "Hello" var y: String? = "World" x = y // Type mismatch,报错 y = x // OK
<font face= 黑体>例子1:指针
<font face= 黑体>咱们先来写一个 Java 的类型转换:
// 定义一个接口 public interface Kotliner { }
// 定义一个类 Person 实现 Kotliner 接口 public class Person implements Kotliner { public final String name; public final int age; public Person(String name, int age) { this.name = name; this.age = age; } public static void main(String[] args) { // 用子类的实例赋值给接口的引用 Kotliner kotliner = new Person("Test", 20); // 这里已经判断了是否是 Person,可是下面仍是要强制类型转换 if (kotliner instanceof Person) { System.out.println(kotliner.name); // 这样写报错 System.out.println(((Person) kotliner).name); // 正确写法 } } }
<font face= 黑体>一样的代码在 Kotlin 中就能够实现智能类型转换,不须要强制类型转换:
val kotliner: Kotliner = Person("Test", 20) if (kotliner is Person) { println((kotliner as Person).name) // 不须要强转,能够智能转换,因此下面的写法就能够了 println(kotliner.name) }
<font face= 黑体>例子2:
<font face= 黑体>下面这段代码定义了一个 value, 类型是 String?,if 判断其不为空,因此在 if 判断这个括号里面,value 的类型会被智能转换成 String,固然出了括号,value 的类型就又是 String? 了。
var value: String? = null value = "Test" if (value != null) { // value: String? ==> String println(value.length) } // value: String? ...
<font face= 黑体>下面这种状况就不支持智能类型转换,由于这个公共变量不少地方均可以访问,因此咱们在判断不为空以后,有可能别的线程又把 tag 改为了空,因此这种状况智能类型转换就失效了。
// 在 main 函数以外定义一个公共变量 var tag: String? = null fun main() { if(tag != null) { // 有可能被改为空 println(tag.length) // 报错,不支持智能类型转换 } }
<font face= 黑体>本篇博客主要讲了 Kotlin 中的空类型安全和智能类型转换,下一节咱们讲 Kotin 中的表达式。
源码 已上传至 github,有须要能够直接下载。