Kotlin Null安全性-Kotlin Nullable

时间:2020-02-23 14:37:31  来源:igfitidea点击:

在本教程中,我们将研究Kotlin Null安全性。
NullPointerException是任何程序员在其项目中目击的最常见的错误类型之一。
让我们看看Kotlin是如何处理的。

Kotlin Null安全

默认情况下,Kotlin编译器不允许任何类型在编译时将其值设置为null。
对于Kotlin,可空性是一种类型。
在较高的级别上,Kotlin类型适合两者之一。

  • 可空性类型
  • 不可为空类型

可空性作为一种类型

我们无法在Kotlin中定义以下语法。

var str: String = "theitroad Kotlin Archives"
str= null //compilation error

var a : String = null //compilation error.

要将类型设置为Nullable,我们需要在该类型后附加一个"?",如下所示。

var a : String? = null
var newStr : String? = "Kotlin Null Safety"
newStr = null

现在,每当我们访问一个Nullable Referernce时,我们都需要谨慎处理null情况。
注意:添加?将变量的类型从String更改为String ?,将Int更改为Int?等等。
最常见的方法是使用if else语句,如下所示。

if(a!=null)
{
print("The value of a is $a")
}
else{
print("Sorry a is null")
}

现在,以上方法可以导致很多嵌套括号。
Kotlin确实提供了使用"安全调用"访问可空引用的更简单方法。

安全调用

要在变量上调用函数或者属性,通常需要执行以下操作。

var a : String = "Hello"
print(a.length)

这不会始终与可空引用一起使用。

var a : String? = "Hi"
print(a.length) //prints 2

a = null
print(a.length) //compilation error

当Nullable引用包含空值时,不能使用点引用。
因此,Kotlin为我们提供了一个安全的调用运算符,可以在可空引用上使用,如下所示。

a = "Hi"
print(a?.length) //prints 2

a = null
print(a?.length) //prints null

安全调用"?。
"仅在值不为null时才执行相关调用。
否则,它将为您打印一个空值。

需要在多个变量上保留空性检查器时,安全调用非常方便,如下所示。

var streetName : String? = address?.locality?.street?.addressLine1

还有一种方法可以在可为空的引用上调用属性。

!!运算符

与安全调用相反,!!也称为非空断言,它将可空引用转换为其不可空类型,而不管它是否为空。
仅当您确定该值不为NULL时,才应使用此选项。
否则会导致NPE异常。

a = null
println(a!!.length) //runtime error.

a = "Hi"
print(a!!.length) //prints 2

安全转换

?运算符也可以用于防止ClassCastException(另一个常见的异常)。

var b : String ="2"
var x : Int? =  b as? Int
println(x) //prints null

在上面的代码中,我们可以安全地使用

as?


如果转换失败,则将该值设置为null,从而防止ClassCastException。
另一个例子:

var array1 : Array<Any?> =  arrayOf("1","2","3")
var i : Int? = array1[0] as? Int
println(i) //prints null
var s : String? = array1[0] as? String
print(s) //prints 1

elvis运算符

到目前为止,只要安全调用运算符返回空值,我们就不会执行任何操作,而是输出空值。
elvis运算符 ?:允许我们设置默认值,而不是null,如下所示。

var newString : String?  = "theitroad.local"
println(newString?.length) //prints 14
newString = null
println(newString?.length?:"-1") //prints -1

elvis运算符等效于以下内容:

if(newString!null)
{
print(newString.length)
}
else{
print("-1")
}

另一个示例:

var streetName : String? = address?.locality?.street?.addressLine1 ?: "Street Name not found"

使用let()

Let函数仅在引用不可为空时才执行指定的lamda函数,如下所示。

newString = " Kotlin from Android"
newString?.let { println("The string value is: $it") }
newString = null
newString?.let { println("The string value is: $it") }

let中的语句是一个lamda表达式。
仅在newString的值不为null时运行。
它包含newString的非null值

使用Also()

除了也通常用于记录值之外,also的行为与" let"相同。
不能将" it"的值分配给另一个变量。
这是let和一起更改的示例。

var c = "Hello"

newString = " Kotlin from Android"
newString?.let { c = it }.also { println("Logging the value: $it") }

注意:" let"中的语句不能放在"也"中。
反之亦然。

筛选出空值

我们可以使用以下函数从集合类型中过滤出Null值:

var array2: Array<Any?> = arrayOf("1", "2", "3", null)
var newArray = array2.filterNotNull()
println(newArray.size) //prints 3

Java互操作性

由于Java不会强迫您将类型声明为Nullable或者Non-Nullable类型,因此Kotlin编译器不会针对以下内容给出错误:

var javaObject = MyClass(null)

如果您设置Java注释@Nullable或者@NotNull,则Kotlin编译器会将其视为Nullable或者Not Nullable引用。