在 Java 和 Objective-C 开发中,空指针带来的相关错误是我们日常开发中的"常客"。而在ArkTS 通过要求开发者显式声明可空类型(如 string | null),并提供可选链操作符(?.)和空值合并操作符(??),将潜在的空指针异常从运行时风险转化为编译时即可发现和处理的错误。这种设计哲学上的转变,不仅极大地提升了代码的健壮性,也引导开发者养成更严谨的编程思维习惯,从源头上构建更加安全可靠的应用。
本篇内容是《精通HarmonyOS NEXT :鸿蒙App开发入门与项目化实战》这本书第四章内容的延续,是咱这本书读者的福利,在本篇内容中通过4个示例说明可空变量的使用,每个示例可以独立的编译及调试,欢迎大家一同来深入了解,甚至可以当作面试题来学习。
对本书感兴趣的同学可以点击以下链接进行购买,及参加 我的班级(华为官方)共同学习
1. 可空类型声明定义及默认值
在 ArkTS 语言中,可空类型是指通过类型系统显式标记的、允许包含 null 或 undefined 值的变量类型。这是 ArkTS 类型安全体系的核心特性之一。
下面的代码示例说明如何定义可空变量或类属性。
// 联合类型声明,allowUndefinedVar类型 允许为string为 undefined
let allowUndefinedVar: string | undefined = undefined;
// 联合类型声明,allowNullVar类型 允许为string和null
let allowNullVar: string | null = null;
class memberAllowNullOrUndefined {
// 联合类型声明,allowUndefinedVar类型 允许为string为 undefined
static allowUndefinedVar: string | undefined = undefined;
// 简写语法:在变量名后添加?,allowUndefinedVar1类型 允许为string为 undefined
static allowUndefinedVar1?: string = undefined;
// 联合类型声明,allowNullVar类型 允许为string和null
static allowNullVar: string | null = null;
}
对应的默认值均为undefined,如下图所示
2. 非空断言访问
非空断言访问(!.)可断言对象非空后访问其属性/方法。若对象实际为null/undefined,会触发运行时错误。基于上面类实例中的三个变量调用为示例,下面写法均会产生运行时错误。
memberAllowNullOrUndefined.allowUndefinedVar!.length
memberAllowNullOrUndefined.allowUndefinedVar1!.length
memberAllowNullOrUndefined.allowNullVar!.length
其中allowUndefinedVar和allowUndefinedVar1报错的信息截图如下
allowNullVar的报错的信息截图如下
可以看出,对于null和undefined的对象,error message还是略有不同。当对上述的这些变量初始化指定字符串时,可正常的执行。这种写法可以帮助研发人员及时的发现异常,适合在核心的流程中使用,并配合异常的保护。
3. 安全链式访问
安全链式访问(?.),相对于非空断言访问,当可能为null/undefined对象的属性/方法以安全链式方式访问时,若对象为空,返回undefined,而并不是直接产生运行时错误。如下代码所示,增多返回undefined。
console.log("俩毛豆 可空变量操作 安全链式访问(?.) m.allowUndefinedVar " + memberAllowNullOrUndefined.allowUndefinedVar);
console.log("俩毛豆 可空变量操作 安全链式访问(?.) m.allowUndefinedVar1?.length " + memberAllowNullOrUndefined.allowUndefinedVar1?.length);
console.log("俩毛豆 可空变量操作 安全链式访问(?.) m.allowNullVar?.length " + memberAllowNullOrUndefined.allowNullVar?.length);
如下图所示
3.1 代码的静态检查
值得一提的是allowUndefinedVar和allowNullVar变量,因为没有初始化,在编译阶段直接就会报错,Error Message: Property 'length' does not exist on type 'never'.如下图所示。
需要对其指定字符串赋值,才可正常编译。但是类属性中的可空变量就没有这样的编译报错。
4. 空值合并
空值合并运算(??),当左侧为null/undefined时返回右侧默认值。空值合并二元运算符??用于检查左侧表达式的求值是否等于null或者undefined。其运算规则是:如果左侧的操作数为null或者undefined,则返回右侧操作数;否则,返回左侧操作数。
在一些语句中a ?? b等价于三元运算符(a != null && a != undefined) ? a : b。如下代码所示(摘自书中内容)。
let userName: string | null = null;
let result = userName ?? "匿名";
// 输出: "可空变量操作 空值合并运算(??) 匿名"(userName值为空)
console.log("可空变量操作 空值合并运算(??) " + result);
userName = "俩毛豆";
result = userName?? "匿名";
// 输出: "可空变量操作 空值合并运算(??) 俩毛豆"(userName值为非空)
console.log("可空变量操作 空值合并运算(??) " + result);
输出的结果如下图所示。
总结:
本文深入探讨ArkTS语言中可空类型的设计优势与实现方式。通过4个独立示例,详细解析了可空类型声明(如string|null)、非空断言(!.)、安全链式访问(?.)和空值合并(??)等特性,展示了如何将空指针异常从运行时风险转化为编译时可检测的错误。这些机制不仅提升代码健壮性,还培养了开发者更严谨的编程思维,是《精通HarmonyOS NEXT :鸿蒙App开发入门与项目化实战》一书中关于类型安全实践的重要内容,适用于鸿蒙应用开发学习和面试准备。
对本书感兴趣的同学可以点击以下链接进行购买,及参加 我的班级(华为官方)共同学习