Kotlin学习之空安全

Kotlin学习之空安全

@(Kotlin学习)

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

一、空安全

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

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

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

Kotlin的类型系统诣在从代码中消除NullPointerException。NPE的唯一可能的原因是:
- 显示调用throw NullPointerException();
- 使用了下文描述的!!操作符;
- 外部Java代码导致的;
- 对于初始化,有一些数据不一致。

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);
}
  • 安全调用操作符(?.)实际上是个语法糖,会被编译为一个三目运算表达式。
  • 如果?.前的对象不为null,则调用?.后的方法或属性,否则就返回null。
  • 如果一个可空变量已经被判断为非空,再次调用它的方法和变量时,会自动将变量转换为非空类型,实现安全调用。

四、Elvis操作符(?:)

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

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

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

在Java中:

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

在Kotlin中:

files?.size ?: "Empty"

可以如下理解Elvis操作符:
- A ?: B 等价于 if(A==null) B
- A ?. B ?: C 等价于 if(A!=null) A.B else C

五、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,有两种办法:
- 显式地throw NullPointerException();
- 使用非空操作符!!。

val l = b!!.length

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

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

学海无涯苦作舟

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员丶星霖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值