Kotlin专题KotlinKotlin编程

Kotlin学习之空安全

2017-12-01  本文已影响132人  程序员丶星霖

Kotlin学习之空安全

Kotlin相对于Java有许多改良的地方,空安全就是其中的一部分,Kotlin因此解决了空指针问题。

一、空安全

Java语言中没有C/C++的指针,取而代之的是引用。在Java支持的四种数据类型(类、接口、数组、基本类型)中,类、接口和数组统称为引用类型,定义一个引用类型变量需要两个步骤:

  1. 定义一个引用类型的变量。
String s;
List<String> l;
int[] n;
  1. 进行初始化(创建对象并使之前定义的引用指向这个对象)。有两种方法:
s = "Hello World"; // String 类型的特殊写法,等同于调用构造方法
l = new ArrayList<>(); // 使用子类型创建对象
n = new int[10];

在Java中,对于没有进行初始化的引用类型变量,调用它们的实例方法或实例属性都会产生NullPointerException,也就是所谓的NPE。而这一切都发生在运行时,编译时不会报错

Kotlin的类型系统诣在从代码中消除NullPointerException。NPE的唯一可能的原因是:

Kotlin解决空安全,而不是消灭NPE,而是允许NPE存在,但只会在它该出现的时候出现。Kotlin区分了可空类型不可空类型

二、可空类型与非空类型

在Kotlin中如下代码:

val s: String = null

会得到一个编译错误。编译器说不能讲null赋给非空的String类型。

在Kotlin中,所有数据类型默认都是非空的,如果想把null赋给它们的对象,需要在类型后加上?,声明为可空类型。

所以上面的代码需要在String后面加上?:

val s: String? = null

所以,在Kotlin中我们只要将变量声明为非空类型,就可以放心地调用它的实例方法和实例变量,不用担心出现NPE。

三、安全调用符(?.)

对于可空类型的变量,应该怎样安全地调用它的属性和方法呢?Kotlin的解决方式是使用?.安全调用符。

如下面Kotlin的函数:

// 安全调用属性
fun printLengthOfString(s: String?) = println(s?.length)

在Java中等同于如下:

public static final void printLengthOfString(@Nullable String s) {
  Integer var1 = (s != null) ? s.length() : null;
  System.out.println(var1);
}

四、Elvis操作符(?:)

这个操作符是三目条件运算符的简略写法。

如果?:左侧表达式非空,Elvis操作符就返回其左侧表达式,否则就返回右侧表达式。请注意,当且仅当左侧为空时,才会对右侧表达式求值

Kotlin中用Elvis操作符配合安全调用符实现简单清晰的空检查和空操作。

在Java中:

(files != null) ? files.length : "Empty"

在Kotlin中:

files?.size ?: "Empty"

可以如下理解Elvis操作符:

五、let函数

let函数可以看做一个加强版的安全操作符,或者另一种写法if not null then语句。

let函数单纯地接收一个函数,然后执行它,返回函数的执行结果。一般情况下,let函数与安全调用符配合使用:

val listWithNulls: List<String?> = listOf("A", null)
for (item in listWithNulls) {
     item?.let { println(it) } // 输出 A 并忽略 null
}

也就是时候安全调用符+let函数就等同于if not null then语句。

六、非空操作符(!!)

要在Kotlin中产生NPE,有两种办法:

val l = b!!.length

b!!会返回一个非空的b值,如果b为空,就会抛出一个NPE异常。

但是,Kotlin并不建议在代码中广泛使用!!操作符,因为这样会浪费Kotlin良好的非空类型的设计,让Kotlin代码中充斥着NPE。

学海无涯苦作舟

我的微信公众号.jpg
上一篇 下一篇

猜你喜欢

热点阅读