Kotlin编程语言使用问号的用途解释

669 阅读3分钟

Kotlin编程语言使用问号(?)符号来表示其许多空值安全功能。

空值安全是现代编程语言的一个特点,它是为了减少(或消除)源代码中引用空值的危险。

为了理解Kotlin的空值安全功能是如何工作的,让我们先看看Java中的一个例子。

下面的代码在Java中是有效的:

class Example {
public static void main(String[] args) {
String myString = null;
myString.length();
}
}

但是当你运行上面的代码时,对myString.length() 的调用会产生一个错误,如下图所示:

Exception in thread "main" java.lang.NullPointerException
at Example.main(example.java:4)

NullPointerException 的发生是因为上面的myString 变量的值是null ,而这个null 的值并不能访问.length() 方法。

Kotlin的设计是为了防止NullPointerException 错误,这就是在该语言中加入null安全特性的原因。

在Kotlin中,你不能将null 赋值给一个类型为String 的变量,如下图所示:

var myString: String = null
// Error: null can not be a value of non-null String type

要想在你的变量中允许null ,你需要在变量类型后面添加一个问号?

var myString: String? = null

然后,该变量就变成了一个可空的String 类型,它可以容纳null 的值。

StringString? 之间的这种不同类型也允许Kotlin编译器在你运行源代码之前报告任何与null 有关的错误。

例如,假设你想检查String? 类型中的length 。默认情况下,Kotlin会抱怨说你需要执行一个安全调用:

var myString: String? = null
myString.length // Error: only safe or asserted call allowed!

对于一个nullable类型的安全调用是通过在属性或方法调用前添加一个问号来完成的。

考虑一下下面的例子:

var myString: String? = null
myString?.length // ok
myString?.uppercase() // ok

上面代码中的属性和方法调用都是安全调用。当变量的值是null ,那么Kotlin只是返回null ,而不执行属性或方法调用。

对属性和方法的非空断言调用

除了上面的安全调用,Kotlin还有非空的断言调用,它使用了双bang操作符 (!!)

非空值断言调用是在你绝对确定nullable类型不是null ,所以你不需要安全调用时使用的。

考虑一下下面的例子:

var myString: String? = null
myString = "abc"
myString!!.length
myString!!.uppercase()

你可以看到,在调用.length.uppercase() 时,myString 的值已经不是null

但是Kotlin仍然抱怨说你需要进行安全调用或者断言调用,因为String? 类型为nullable。

因为我们确定myString 的值是abc ,所以你可以使用!! 操作符做一个非空的断言式调用。

当你对一个有null 值的变量进行非空的断言调用时,Kotlin会抛出NullPointerException 错误:

var myString: String? = null
myString!!.length // Error: NullPointerException

正如你所看到的,Kotlin中的问号是一个伟大的功能,它可以帮助你避免由null 值引起的错误。

安全转换的问号

问号也可以在使用as 关键字来铸造一个变量时使用:

var myVar: Any = "String"
var myInt: Int? = myVar as? Int // returns null

当铸造不可能时,那么Kotlin将返回null ,而不是抛出ClassCastException

问号在elvis操作中的应用

最后,问号也被用于Kotlin的elvis操作符(?:),用来编写一个条件表达式:

var myStr: String? = null
var myVar: String = myStr ?: "Hello"

你可以在这里了解更多关于elvis运算符的信息。

现在你已经知道了问号是如何在Kotlin中用于空值安全功能的。干得好!👍