好懂版一句话:
! 就是你拍胸脯跟 Dart 保证:“这个变量绝对不是 null**,你直接用,出事我负责!”**
1. 先看场景:为什么要用 !
你有一个可空类型变量:
String? name;
可空类型不能直接调用属性/方法:
print(name.length); // 报错:name 可能为 null
这时候你又确定它不可能为空,就可以用 ! 强制解包:
print(name!.length); // ✅ 不报错了
2. ! 到底干了啥?
- 把
String?强行变成String - 告诉 Dart:别检查 null 了,我保证它有值
但风险是:
如果它真的是 null ,程序直接崩溃!
String? name;
print(name!.length); // 🔥 直接崩溃:Null check operator used on a null value
3. 什么时候可以用 !?
只有一种情况:
你 100% 确定它不可能是 null ,只是 Dart 分析不出来。
常见场景:
① 你刚判空完,但 Dart 没识别到(比如类变量)
class Person {
String? name;
void test() {
if (name != null) {
// 类变量不会类型提升,Dart 依然认为可能空
print(name!.length); // 这里只能用 !
}
}
}
② 第三方库返回可空,但文档说不会返回 null
final user = getUser();
print(user!.name);
③ 延迟初始化,确保使用前已赋值
String? _name;
void init() {
_name = "Tom";
}
void printName() {
// 你保证 init 一定先调用过
print(_name!.length);
}
4. 什么时候绝对不要用 !?
- 不确定是不是 null
- 数据来自接口、外部输入、文件
- 列表可能为空、数据可能缺失
乱用就是在埋线上崩溃点。
5. 更好的替代方案(比 ! 安全得多)
① 用局部变量 + 类型提升(最推荐)
void test() {
final local = name;
if (local != null) {
print(local.length); // 不用 !
}
}
② 用 ?. 空安全调用
print(name?.length); // 为 null 时返回 null,不崩溃
③ 用 ?? 提供默认值
print(name?.length ?? 0);
极简总结
!= 强制把可空类型当非空用- 优点:能绕过空检查,代码好写
- 缺点:真为 null 就直接崩
- 原则:不确定就别用,确定再用