Flutter 零基础入门(十一):空安全(Null Safety)基础

Flutter&Dart零基础入门教程(一)
Flutter 零基础入门(二):Dart 字符串与字符串插值
Flutter 零基础入门(三):条件判断与逻辑运算
Flutter零基础入门(四):switch、多分支判断与循环
Flutter零基础入门(五):List列表与遍历
Flutter 零基础入门(六):Map 键值对与简单数据模型
Flutter 零基础入门(七):函数(Function)与代码封装
Flutter 零基础入门(八):Dart 类(Class)与对象(Object)
Flutter 零基础入门(九):构造函数、命名构造函数与 this 关键字
Flutter 零基础入门(十):final、const 与不可变数据

Flutter 零基础入门(十一):空安全(Null Safety)基础

在前面的学习中,我们已经学会了:

  • 变量与数据类型
  • List、Map、Class
  • final、const 与不可变数据

但你在实际写 Dart 代码时,很可能已经遇到过类似提示:

  • ❌ A value of type 'null' can't be assigned
  • ❌ The property 'xxx' can't be accessed because it is potentially null

这些问题,都指向同一个核心概念:

👉 空安全(Null Safety)


一、什么是 null?

null 表示:

什么都没有 / 不存在 / 未赋值

例如:

  • 用户还没登录
  • 数据还没加载
  • 接口还没返回结果

在早期语言中,null 非常容易导致运行时崩溃(空指针异常)。


二、为什么 Dart 要引入空安全?

在没有空安全的情况下:

dart 复制代码
String name;
print(name.length); // ❌ 运行时崩溃

问题是:

  • 编译时不会报错
  • 错误在运行时才出现

📌 Dart 的目标是:

尽可能在编译阶段发现问题

于是就有了 Null Safety


三、默认情况下:变量不能为 null

在空安全开启后(Flutter 默认开启):

复制代码
String name = 'Tom';
name = null; // ❌ 编译报错

结论:

默认情况下,所有变量都不允许为 null

这是 Dart 空安全的第一条核心规则。


四、可空类型:?

如果一个变量确实可能为空,你必须明确告诉 Dart。

1️⃣ 使用 ? 声明可空类型

复制代码
String? name;

含义:

  • name 可以是 String
  • 也可以是 null

2️⃣ 给可空变量赋值

复制代码
String? name = null;
name = 'Tom';

这样写是完全合法的。


五、访问可空变量的问题

来看一个常见错误:

复制代码
String? name = 'Tom';
print(name.length); // ❌ 报错

为什么?

因为:

  • Dart 不确定 name 是否为 null
  • 如果是 null,访问 .length 就会崩溃

六、解决方式一:判空(if 判断)

复制代码
if (name != null) {
  print(name.length);
}

这是最安全、最推荐的方式。

📌 原则:

先判断,再使用


七、解决方式二:!(非空断言)

复制代码
print(name!.length);

! 的含义是:

"我保证这里一定不是 null"

⚠️ 注意:

  • 如果你判断错了
  • 程序仍然会在运行时崩溃

📌 使用建议:

少用、慎用、明确场景再用


八、解决方式三:?.(安全调用)

复制代码
print(name?.length);

含义:

  • 如果 name 不为 null → 返回长度
  • 如果 name 为 null → 返回 null

这是 Dart 提供的非常优雅的写法


九、??:提供默认值

复制代码
String? name;
print(name ?? 'Guest');

含义:

  • 如果 name 为 null
  • 就使用 'Guest'

📌 在 Flutter UI 中非常常见。


十、空安全与函数参数

1️⃣ 参数默认不可为空

复制代码
void greet(String name) {
  print('Hello $name');
}

调用时:

复制代码
greet(null); // ❌ 报错

2️⃣ 可空参数写法

复制代码
void greet(String? name) {
  print('Hello ${name ?? 'Guest'}');
}

十一、空安全与类属性(非常重要)

复制代码
class User {
  final String name;
  final int age;

  User(this.name, this.age);
}

这里:

  • name、age 必须有值
  • 对象一旦创建就是"完整状态"

如果属性可能为空:

复制代码
class User {
  String? avatar;
}

📌 Dart 强制你 在设计阶段就想清楚数据是否可能为空


十二、一个综合示例

复制代码
class User {
  final String name;
  final int? age;

  User(this.name, this.age);
}

void printUser(User user) {
  print('姓名:${user.name}');
  print('年龄:${user.age ?? '未知'}');
}

这个例子体现了:

  • 可空类型
  • ?? 默认值
  • 空安全的真实用法

十三、空安全的核心思想总结

空安全不是为了让你多写符号,而是为了:

  • 提前发现问题
  • 减少运行时崩溃
  • 强迫你设计清晰的数据结构

📌 一句话理解:

Dart 不允许你"模棱两可"地使用数据


十四、总结

本篇你已经学会了:

  • 什么是 null
  • 什么是空安全
  • ?!?.?? 的含义
  • 如何在变量、函数、类中使用空安全

你已经完成了从:

"随便用数据" → "严谨使用数据" 的关键升级


🔜 下一篇预告

《Flutter 零基础入门(十二):枚举(enum)与状态管理的第一步》

下一篇我们将学习:

  • 什么是 enum
  • 为什么 enum 比 int / String 更安全
  • 用 enum 表示状态
  • 为 Flutter 页面状态打基础

从下一篇开始,我们会逐步进入:

Flutter 状态与 UI 逻辑的核心世界

相关推荐
我命由我123452 小时前
Android 广播 - 静态注册与动态注册对广播接收器实例创建的影响
android·java·开发语言·java-ee·android studio·android-studio·android runtime
ZH15455891312 小时前
Flutter for OpenHarmony Python学习助手实战:自动化脚本开发的实现
python·学习·flutter
island13142 小时前
CANN ops-nn 算子库深度解析:核心算子(如激活函数、归一化)的数值精度控制与内存高效实现
开发语言·人工智能·神经网络
xcLeigh2 小时前
Python入门:Python3 requests模块全面学习教程
开发语言·python·学习·模块·python3·requests
xcLeigh2 小时前
Python入门:Python3 statistics模块全面学习教程
开发语言·python·学习·模块·python3·statistics
秋邱3 小时前
用 Python 写出 C++ 的性能?用CANN中PyPTO 算子开发硬核上手指南
开发语言·c++·python
wenzhangli73 小时前
ooderA2UI BridgeCode 深度解析:从设计原理到 Trae Solo Skill 实践
java·开发语言·人工智能·开源
晚烛3 小时前
CANN + 物理信息神经网络(PINNs):求解偏微分方程的新范式
javascript·人工智能·flutter·html·零售
灵感菇_3 小时前
Java 锁机制全面解析
java·开发语言
wazmlp0018873693 小时前
python第三次作业
开发语言·python