【安卓】Kotlin 空类型安全与智能类型转换

一、前言

<font face= 黑体>在 Kotlin 中的类与接口 中我们已经讲了 Kotlin 的 类、接口 和 扩展方法,今天我们来讲 Kotlin 中的 空类型安全 和 智能类型转换。

二、Kotlin 空类型安全

2.1、空类型安全概念

<font face= 黑体>Java 语言中是没有空类型安全这一概念的,所以写 Java 代码经常会出现空指针异常,但是 Kotlin 致力于消除空引用所带来的危险,所以就有了空类型安全概念。

<font face= 黑体>下面这段代码在 Kotlin 中是无法编译通过的,因为 Kotlin 的 String 是不能接受空值的,所以这个赋值操作是不被允许的。

var nonNull: String = "Hello"

nonNull = null // 不可空类型,不能赋值为 null

// 访问长度的话,不需要空判断

val length = nonNull.length

<font face= 黑体>IDE 报错如下所示:
【安卓】Kotlin 空类型安全与智能类型转换

<font face= 黑体>但是如果我们非得定义一个空值,也是有办法的,Kotlin 为了 100% 兼容 Java,必须得实现接收空值,所以要接收空值可以在定义的时候加一个 ?。

<font face= 黑体>但是这个时候这个变量就可能是空值,所以访问的时候就会比较严格,比如下面代码中的 nullable.length 就会报错,因为可能触发空指针异常。

var nullable: String? = "Hello"

nullable = null // 可空类型,编译通过

val length = nullable.length // 可能触发空指针,编译保报错

<font face= 黑体>IDE 报错如下所示:
【安卓】Kotlin 空类型安全与智能类型转换
<font face= 黑体>这个时候我们想 nullable.length 不报错可以:

  1. <font face= 黑体>当我们确定 nullable 不可能为空的时候,可以将 nullable 强转为不可空类型,如下所示:

    var nullable: String? = "Hello"

    // 不会报错了(自己已经知道了,这个 nullable 不可能为空)

    val length = nullable!!.length

  2. <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

2.2、空类型的继承关系

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

2.3、Kotlin 空类型安全回顾

【安卓】Kotlin 空类型安全与智能类型转换

三、Kotlin 智能类型转换

3.1、智能类型转换例子

<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:

var value: String? = null

value = "Test"

if (value != null) {

// value: String? ==> String

println(value.length)

}

// value: String?

...

3.2、不支持智能类型转换的情况

// 在 main 函数之外定义一个公共变量

var tag: String? = null

fun main() {

if(tag != null) {

// 有可能被改成空

println(tag.length) // 报错,不支持智能类型转换

}

}

3.3、几个建议

  • <font face= 黑体>尽可能使用 val 来声明不可变引用,让程序的含义更加清晰确定;
  • <font face= 黑体>尽可能减少函数对外部变量的访问;
  • <font face= 黑体>必要的时候曾创建局部变量指向外部变量,避免因它变化引起程序错误。

3.4、Kotlin 智能类型转换

【安卓】Kotlin 空类型安全与智能类型转换

四、小结

<font face= 黑体>本篇博客主要讲了 Kotlin 中的空类型安全和智能类型转换,下一节我们讲 Kotin 中的表达式。

五、源码

源码 已上传至 github,有需要可以直接下载。

以上是 【安卓】Kotlin 空类型安全与智能类型转换 的全部内容, 来源链接: utcz.com/a/97837.html

回到顶部