深入理解Dart中空安全

269 阅读4分钟

屏幕截图 2025-01-14 203817.png

前言

  • 学习之路需深耕细作,切勿轻视任一知识点,因其存在必蕴含深意

在软件开发中,空值(null)的处理一直是一个令人头疼的问题。空指针异常不仅会导致程序崩溃,还会增加调试和维护的难度。Dart 2.12引入了空安全(Sound Null Safety)特性,这一特性旨在帮助开发者检测并避免使用空值,从而提高代码的健壮性和可靠性。本文将详细介绍Dart中空安全的基本概念、使用方法以及它如何改变我们的编码习惯。

基本概念

空安全的意思是每个变量都不能为空或提前明确声明其可为空。在Dart中,通过以下方式声明变量的可空性:

  • 非空变量:默认情况下,Dart认为所有变量都是非空的。例如,String name = "Alice";表示name是一个非空字符串。
  • 可空变量:在变量类型后添加?表示该变量可以为空。例如,String? nullableName;表示nullableName是一个可以为空的字符串。

使用方法

1. 空值合并运算符 ??

空值合并运算符??用于检查一个表达式是否为null。如果表达式的结果不是null,则返回该结果;如果结果是null,则返回一个指定的默认值。

String? a; 
String b = a ?? "猜猜我是谁"; // 如果 a 是 null,则 “猜猜我是谁”被赋值为 b 的值;否则,a 保持不变
print(b);//输出:猜猜我是谁
2. 空感知赋值运算符??=

??= 运算符检查其左侧的操作数是否为 null。如果左侧的操作数不是 null,则不会改变该变量的值;如果左侧的操作数是 null,则将该变量赋值为右侧操作数的值。

String a; 
String b = "我是b"; 
a ??= b; // 如果 a 是 null,则 a 被赋值为 b 的值;否则,a 保持不变
print(a); // 输出:我是b 
3.空全调用运算符?.

如果?.调用的对象是null,则整个表达式的结果为null,而不会抛出空指针异常。

String? nullableName; // 如果 nullableName 为 null,则 length 也为 null 
int? length = nullableName?.length;
print(length); // 输出: null
4.非空断言!

当确定一个可空变量在某个时刻不为空时,可以使用非空断言!来告诉编译器。

 	String? string;

 	void main() {

 	  string = "Hello, World!";

 	  print(string!.length); // 输出13

 	}

5. 使用late关键字延迟变量初始化

当变量的值在后续代码中才能确定时,可以使用late关键字延迟初始化。

late String lateString;
void main() {
    lateString = "Hello, Dart!";
    print(lateString);、//输出  Hello, Dart!
}
6.required 修饰符

使用 required 修饰的参数,在函数调用时必须提供值,且该值不能为空。这有助于避免在函数体内部处理空值的情况,从而提高代码的健壮性和可读性。

void printPersonInfo({required String name, required int age})  {
    print('Name: $name, Age: $age'); 
} 
// 正确的调用方式 
printPersonInfo(name: 'Alice', age: 30); 
// 错误的调用方式(会导致编译错误,因为缺少 required 参数)
// printPersonInfo();
// printPersonInfo(age: 30);

优点

  • 在引入空安全之前,Dart的类型系统中,空值(null)被视为所有类型的子类。这意味着任何类型的变量都可以接受一个null值。(如下图)

屏幕截图 2025-01-14 211429.png

  • 引入空安全后,Dart将空值(null)独立出来,不再视为所有类型的子类。这意味着除了特殊的Null类型允许传递null值外,其他类型均不允许接受null值。(如下图)

屏幕截图 2025-01-14 211448.png

1.提高代码的健壮性
  • 空安全允许开发者明确区分可为空的类型和不可为空的类型,这有助于在编译阶段就捕获潜在的空引用错误,从而避免这些错误在运行时导致程序崩溃。
2.增强代码的可读性和可维护性
  • 使用空安全特性,开发者需要在代码中显式地声明变量的可空性或不可为空性,这使得代码更加清晰易懂。
3. 提高代码质量
  • 明确的空值处理规则使得代码逻辑更加清晰,减少了不必要的 if (x != null) 检查。