Dart Null 值
最后修改日期:2025 年 6 月 4 日
在 Dart 中,null 表示没有值。它是一个特殊值,表示一个变量尚未被赋予任何对象引用。
随着 Dart 2.12 中引入的空安全,变量默认不能包含 null。要允许 null 值,我们必须显式地将它们声明为可空类型。
基本 Null 概念
Dart 的类型系统区分可空类型和非可空类型。? 后缀表示可空类型。! 运算符断言一个值是非 null 的。
空感知运算符有助于安全地处理潜在的 null 值。这些包括 ??, ?., 和 ??=。它们提供了处理 null 情况的简洁方式。
理解 null 对于编写健壮的 Dart 代码至关重要。正确的 null 处理可以防止运行时 null 引用异常,并使代码更具可预测性。
可空类型 vs 非可空类型
Dart 2.12+ 默认强制执行空安全。变量不能为 null,除非使用 ? 类型后缀显式声明为可空。
void main() {
// Non-nullable variable
String name = 'Alice';
// name = null; // Compile-time error
// Nullable variable
String? nullableName = 'Bob';
nullableName = null; // Allowed
print('Name: $name');
print('Nullable name: $nullableName');
}
第一个变量不能为 null,而第二个变量可以。尝试将 null 赋值给非可空变量会导致编译时错误。
$ dart main.dart Name: Alice Nullable name: null
Null 断言运算符
! 运算符断言一个表达式是非 null 的。当您确定可空变量包含非 null 值时,请使用它。
void main() {
String? maybeName = 'Alice';
// Without assertion
print('Length: ${maybeName?.length}');
// With assertion
print('Length: ${maybeName!.length}');
maybeName = null;
// print('Length: ${maybeName!.length}'); // Runtime error
}
第一个 print 使用安全导航 (?.)。第二个使用 ! 断言非 null。被注释掉的行如果取消注释,将引发运行时异常。
$ dart main.dart Length: 5 Length: 5
空感知运算符
Dart 提供了几个运算符来进行简洁的 null 处理。?? 运算符在遇到 null 时提供一个默认值。
void main() {
String? name;
// Null coalescing operator
String displayName = name ?? 'Guest';
print('Welcome, $displayName!');
// Null-aware assignment
name ??= 'Anonymous';
print('Hello, $name!');
// Null-aware access
print('Name length: ${name?.length}');
}
当 name 为 null 时,?? 运算符提供 'Guest'。??= 运算符仅在变量为 null 时才赋值。?. 运算符安全地访问属性。
$ dart main.dart Welcome, Guest! Hello, Anonymous! Name length: 9
集合中的空安全
Dart 中的集合可以包含 null 值,除非显式限制。我们可以指定列表元素或映射值是否可以为 null。
void main() {
// List with nullable elements
List<int?> nullableNumbers = [1, null, 3];
print('Nullable numbers: $nullableNumbers');
// Map with nullable values
Map<String, String?> userData = {
'name': 'Alice',
'email': null
};
print('User data: $userData');
// Non-nullable list
List<int> numbers = [1, 2, 3];
// numbers.add(null); // Error
}
第一个列表和映射允许 null 值。最后一个列表禁止 null。类型系统在编译时强制执行这些约束。
$ dart main.dart
Nullable numbers: [1, null, 3]
User data: {name: Alice, email: null}
可选参数和 Null
Dart 函数可以具有默认为 null 的可选参数。命名参数默认为可选,而位置参数需要 []。
void greet(String name, [String? title]) {
print('Hello ${title != null ? '$title ' : ''}$name');
}
void printUser({String name = 'Guest', int? age}) {
print('Name: $name, Age: ${age ?? 'unknown'}');
}
void main() {
greet('Alice'); // No title
greet('Bob', 'Dr.'); // With title
printUser(); // Default name
printUser(name: 'Charlie', age: 30); // All parameters
}
greet 函数有一个可选的位置参数。printUser 使用带有默认值的命名参数。两者都展示了 null 处理模式。
$ dart main.dart Hello Alice Hello Dr. Bob Name: Guest, Age: unknown Name: Charlie, Age: 30
最佳实践
- 最小化可空类型:只有当 null 是有效情况时才使用 ?。
- 使用默认值:可能时,优先使用 ?? 而不是 !。
- 记录 Null 情况:清楚地标明何时预期 null。
- 早期验证:在函数中尽早检查 null。
- 空感知运算符:使用它们进行更清晰的 null 处理。
来源
本教程通过实际示例涵盖了 Dart 的 null 值,展示了空安全特性和模式。
作者
列出 所有 Dart 教程。