编程漫谈系列(5)空安全(Null Safety)
空安全
所谓空安全,是指编程语言在声明类型时,将同一种类型分为可空类型(Nullable)和非可空类型(Non-Nullable),对两种类型区别对待。
可空类型与非可空类型
可空类型的变量可以设置为空,声明时可以不设置初值(缺省值为空),使用时则需要检查是否为空,否则在运行期容易引发空指针异常。
非可空类型的变量不可设置为空,声明时必须设置非空初值,使用时无须检查是否为空,不会在运行期引发空指针异常。
Swift | Kotlin | Dart 2.12 | C# 8.0 | |
---|---|---|---|---|
可空类型(基本类型) | var i: Int? = 3 i = nil // ok |
var i: Int? = 3 i = null // ok |
int? i = 3; i = null; // ok |
int? i = 3; i = null; // ok |
可空类型(非基本类型) | var s: String? = "abc" s = nil // ok |
var s: String? = "abc" s = null // ok |
String? s = "abc"; s = null; // ok |
string? s = "abc"; s = null; // ok |
非可空类型(基本类型) | var i: Int = 3 // i = nil // error |
var i: Int = 3 // i = null // error |
int i = 3; // i = null; // error |
int i = 3; // i = null; // error |
非可空类型(非基本类型) | var s: String = "abc" // s = nil // error |
var s: String = "abc" // s = null // error |
String s = "abc"; // s = null; // error |
string s = "abc"; // s = null; // error |
对于 Kotlin 之类的现代编程语言,不仅 Int 之类的基本标量类型存在非可空类型,连 String 之类的复杂类型也存在非可空类型。
对于 Java 之类的传统编程语言,通常只有 int 之类的基本标量类型存在非可空类型,而 String 之类的复杂类型则不存在非可空类型。
Java | C#(8.0之前) | |
---|---|---|
可空类型(基本类型) | Integer i = 3; i = null; // ok |
int? i = 3; i = null; // ok |
可空类型(非基本类型) | String s = "abc"; s = null; // ok |
string s = "abc"; s = null; // ok |
非可空类型(基本类型) | int i = 3; // i = null; // error |
int i = 3; // i = null; // error |
检查是否为空
取值 | 赋值 | 调用方法 | |
---|---|---|---|
Swift(运算符检查) | c = a?.b | a?.b = c | a?.f() |
Swift(手动检查) | c = a == nil ? nil : a.b | if a != nil { a.b = c } |
if a != nil { a.f() } |
Kotlin(运算符检查) | c = a?.b | a?.b = c | a?.f() |
Kotlin(手动检查) | c = if (a == null) null else a.b | if (a != null) a.b = c | if (a != null) a.f() |
C#(运算符检查) | c = a?.b; | 无 | a?.f(); |
C# Java(手动检查) |
c = a == null ? null : a.b; | if (a != null) a.b = c; | if (a != null) a.f(); |
Kotlin 之类的现代编程语言为可空类型的检查提供了 ?. 运算符,代码更为简洁。
Java 之类的传统编程语言在检查可空类型时只能使用 if 语句或条件运算符,代码稍显冗长。