# nullSafety

返回:flutter

TIP

随着 Flutter 1.20 正式版的发布,Dart 2.9 中的 null safety 已经可以是试验性使用,所以本篇翻译将介绍 Dart 中的 null safety 是什么。

对于 Dart 团队而言今天是 null safety 技术预览的一个重要里程碑,null safety 可以帮助开发者避免一些日常开发中很难被发现的错误,并且额外的好处是可以改善性能,现在 null safety 的早期技术预览已经发布,期待大家的使用反馈。

# 为什么需要 null safety

Dart 是一种类型安全的语言,这意味着当开发者获取某种类型的变量时,编译器可以保证它是该类型,但是类型安全本身不能保证变量不是 null。

Null errors 非常常见的问题,在 GitHub 上 可以搜索到成千上万由于 null 导致 Dart 代码出现异常的问题,甚至有成千上万的 commits 试图解决这些问题。

# 可靠的 null safety

Dart 的 null safety 是可靠的,这意味着 Dart 可以 100% 确保,在上面的示例中 files 列表及其中的元素不能为 null 。当 Dart 分析代码并确定某个变量不可为空时,该变量将始终不能为空:如果你在 debugger 模式检查正在运行的代码,你将会发现 non-nullability 会在运行时保留。

Dart 的 null safety 可靠还具有另一个受欢迎的作用:可以让程序变得可以更小,更快。因为 Dart 可以确定 files 永远不会 null,所以 Dart 可以优化执行。例如 Dart 提前(AOT)编译可以生成更小、更快的本机代码,因为当知道变量不会为空时,不需要添加对 null 的检查。

我们初步已经看到了一些非常有希望的结果,例如在 Flutter framework 模拟渲染模式的 microbenchmark 测试中看到了 19%的性能提升。

# 设计原则

在开始针对 null safety 的详细设计之前,Dart 团队定义了以下三个核心原则:

# 默认情况下不可为空

除非开发者明确告知 Dart 变量可以为 null,否则它将认为该变量不可为空。选择这个作为默认选项,因为我们发现 non-nullable 是迄今为止 API 中最常见的选择。

# 逐步采用

因为还有有很多 Dart 代码需要修改,必须把它们逐步迁移到 null safety。在同一项目中应该可以包含 null safety 代码和 non-null-safe 代码,另外我们还将提供工具来帮助开发者进行迁移。

# 完全可靠

如上所述 Dart 的 null safety 是可靠的,将整个项目和依赖项迁移到 null 安全之后,将获得稳健性带来的全部好处。

# 声明变量的 null safety

核心语法很简单,提供一些不同方式来声明 non-nullable 变量,并且默认值是不可为空的,因此这些声明看起来和之前好像一样,但是它们的含义发生了变化。

// In null-safe Dart, none of these can ever be null.
var i = 42;
final b = Foo();
String m = '';
1
2
3
4

Dart 将确保绝不会分配给上述变量任何 null 值。如果尝试执行 i = null,则会出现静态分析错误和红色的弯曲提示,并且无法继续编译。

如果开发者希望变量可为空,如下所示则可以使用? :

// These are all nullable variables.
int? j = 1; // Can be null later.
final Foo? c = getFoo(); // Maybe the function returns null.
String? n; // Is null at first. Can be null at any later time, too.
1
2
3
4

另外也可以将 ? 在运用到其他需要的地方:

// In function parameters.
void boogie(int? count) {
// It's possible that count is null.
}
// In function return values.
Foo? getFoo() {
// Can return null instead of Foo.
}
// Also: generics, typedefs, type checks, etc.
// And any combination of the above.
1
2
3
4
5
6
7
8
9
10

但是,我们是希望你可以不需要使用到 ? ,因为绝大多数类型都是可以不必为空的。