空安全的核心思想
**Dart 的空安全(null safety)**是 Dart 2.12 开始引入的重要特性,能让你的程序更安全地处理 null
,减少运行时空指针错误(NullPointerException)。
核心思想:“非空即安全,空值要声明”
在空安全模式下:
- 变量默认非空:
int x = 5;
表示 x 永远不可能为null
- 需要允许 null 时必须显式声明:
int? x;
才表示 x 可以为null
非空类型与可空类型
类型写法 | 含义 |
---|---|
int |
不能为 null |
int? |
可以为 null |
示例:
void main() {
int a = 5; // ✅ 非空
// a = null; // ❌ 编译报错:非空变量不能赋 null
int? b; // ✅ 可空
b = null; // ✅
}
检查 null 的几种方式
if 判断
int? b;
if (b != null) {
print(b + 1); // 编译器知道 b 不为 null 了
}
条件访问 ?.
String? name;
print(name?.length); // 如果 name 为 null,返回 null,不会抛异常
默认值 ??
String? name;
print(name ?? '默认名字'); // name 为 null 时用默认值
默认赋值 ??=
String? name;
name ??= '默认名字'; // 如果 name 为 null,则赋值
非空断言 !
(谨慎)
String? name;
print(name!.length); // 断言 name 一定不为 null,否则运行时抛异常
延迟初始化(late
)
空安全要求变量初始化前就必须有值。如果你确定稍后会赋值,可以用 late
:
late String name;
name = 'Dart';
print(name); // OK
注意:如果 late
变量在使用前没赋值,会抛运行时错误。
class WPHttpService extends GetxService {
late final Dio _dio;
@override
void onInit() {
...
_dio = Dio(options);
...
}
加上 late
后就可以不用构造函数的时候初始化了
可空类型和方法返回值
String? findUser(int id) {
if (id == 1) return 'Alice';
return null; // 返回 null 是允许的
}
void main() {
String? user = findUser(2);
print(user ?? '未知用户');
}
类型提升(null check promotion)
Dart 会在检查变量非空后,自动把类型从 T?
提升为 T
:
void printLength(String? text) {
if (text != null) {
// 这里 text 类型变成 String(非空)
print(text.length);
}
}
8. 小结对照表
语法 | 作用 |
---|---|
T? |
声明可空类型 |
?. |
只有非空才访问成员 |
?? |
可空时用默认值 |
??= |
为空时赋默认值 |
! |
断言不为空(风险) |
late |
延迟初始化 |
集合与空安全
list
List<String?>? l;
l = [];
l.add(null);
l.add('a');
print(l);
类型 | 集合是否可空 | 数据项是否可空 |
---|---|---|
List<String> |
no | no |
List<String>? |
yes | no |
List<String?> |
no | yes |
List<String?>? |
yes | yes |
Map
Map<String, String?>? m;
m = {};
m['a'] = 'b';
m['b'] = null;
print(m);
类型 | 集合是否可空 | 数据项是否可空 |
---|---|---|
Map<String, int> |
no | no* |
Map<String, int>? |
yes | no* |
Map<String, int?> |
no | yes |
Map<String, int?>? |
yes | yes |
*
:表示可能返回空
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1909773034@qq.com