变量
这是一个创建变量并初始化它的例子
var name = 'Bob';
变量存储引用。名为 name
的变量包含对值为“Bob”的 String
对象的引用。
name
变量的类型被推断为 String
,但您可以通过指定它来更改该类型。如果对象不限于单一类型,请指定 Object
类型(或在必要时指定 dynamic
)。
Object name = 'Bob';
另一种选择是显式声明将要推断的类型
String name = 'Bob';
空安全
#Dart 语言强制执行健全的空安全。
空安全可以防止因意外访问设置为 null
的变量而导致的错误。该错误称为空指针解引用错误。当您访问属性或调用计算结果为 null
的表达式上的方法时,会发生空指针解引用错误。此规则的例外情况是当 null
支持该属性或方法时,例如 toString()
或 hashCode
。使用空安全,Dart 编译器会在编译时检测到这些潜在错误。
例如,假设您要查找 int
变量 i
的绝对值。如果 i
为 null
,则调用 i.abs()
会导致空指针解引用错误。在其他语言中,尝试这样做可能会导致运行时错误,但 Dart 的编译器禁止这些操作。因此,Dart 应用不会导致运行时错误。
空安全引入了三个关键更改
当您为变量、参数或其他相关组件指定类型时,您可以控制该类型是否允许
null
。要启用可空性,请在类型声明的末尾添加?
。dartString? name // Nullable type. Can be `null` or string. String name // Non-nullable type. Cannot be `null` but can be string.
您必须先初始化变量才能使用它们。可空变量默认为
null
,因此它们默认情况下会被初始化。Dart 不会为不可空类型设置初始值。它强制您设置初始值。Dart 不允许您观察未初始化的变量。这可以防止您访问接收器类型可以为null
但null
不支持所用方法或属性的属性或调用方法。您不能访问具有可空类型的表达式的属性或调用其方法。同样的例外情况适用于
null
支持的属性或方法,如hashCode
或toString()
。
健全的空安全将潜在的运行时错误转换为编辑时分析错误。当非空变量出现以下情况时,空安全会标记该变量:
- 未使用非空值初始化。
- 分配了
null
值。
此检查允许您在部署应用之前修复这些错误。
默认值
#具有可空类型的未初始化变量的初始值为 null
。即使是数字类型的变量也最初为 null,因为数字(如 Dart 中的所有其他内容)都是对象。
int? lineCount;
assert(lineCount == null);
使用空安全,您必须在使用之前初始化不可空变量的值
int lineCount = 0;
您不必在声明局部变量时对其进行初始化,但您需要在它被使用之前为其赋值。例如,以下代码是有效的,因为 Dart 可以检测到在 lineCount
传递给 print()
时,它是非空的
int lineCount;
if (weLikeToCount) {
lineCount = countLines();
} else {
lineCount = 0;
}
print(lineCount);
顶级变量和类变量会被延迟初始化;初始化代码会在第一次使用该变量时运行。
延迟变量
#late
修饰符有两个用例
- 声明在声明后初始化的不可空变量。
- 延迟初始化变量。
通常,Dart 的控制流分析可以检测到何时在非空变量被使用之前将其设置为非空值,但有时分析会失败。两种常见情况是顶级变量和实例变量:Dart 通常无法确定它们是否已设置,因此不会尝试。
如果您确定变量在被使用之前已设置,但 Dart 不同意,您可以通过将该变量标记为 late
来修复错误
late String description;
void main() {
description = 'Feijoada!';
print(description);
}
当您将变量标记为 late
但在其声明时对其进行初始化时,则初始化器会在第一次使用该变量时运行。这种延迟初始化在以下两种情况下非常方便
- 可能不需要该变量,并且初始化它的成本很高。
- 您正在初始化实例变量,并且其初始化器需要访问
this
。
在以下示例中,如果从未使用过 temperature
变量,则永远不会调用昂贵的 readThermometer()
函数
// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.
Final 和 const
#如果您不打算更改变量,请使用 final
或 const
,而不是 var
或添加到类型。最终变量只能设置一次;const 变量是编译时常量。(Const 变量是隐式 final。)
这是一个创建和设置 final
变量的示例
final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
您无法更改 final
变量的值
name = 'Alice'; // Error: a final variable can only be set once.
对于您希望成为编译时常量的变量,请使用 const
。如果 const 变量在类级别,请将其标记为 static const
。在声明变量的位置,将该值设置为编译时常量,例如数字或字符串字面量、const 变量或对常数进行算术运算的结果
const bar = 1000000; // Unit of pressure (dynes/cm2)
const double atm = 1.01325 * bar; // Standard atmosphere
const
关键字不仅仅用于声明常量变量。您还可以使用它来创建常量值,以及声明创建常量值的构造函数。任何变量都可以具有常量值。
var foo = const [];
final bar = const [];
const baz = []; // Equivalent to `const []`
您可以从 const
声明的初始化表达式中省略 const
,就像上面的 baz
一样。有关详细信息,请参阅请勿冗余地使用 const。
即使一个非 final、非 const 的变量曾经拥有 const
值,你仍然可以更改它的值。
foo = [1, 2, 3]; // Was const []
你不能更改 const
变量的值。
baz = [42]; // Error: Constant variables can't be assigned a value.
你可以定义使用类型检查和类型转换 (is
和 as
),集合 if
和展开操作符 (...
和 ...?
) 的常量。
const Object i = 3; // Where i is a const Object with an int value...
const list = [i as int]; // Use a typecast.
const map = {if (i is int) i: 'int'}; // Use is and collection if.
const set = {if (list is List<int>) ...list}; // ...and a spread.
有关使用 const
创建常量值的更多信息,请参阅列表、映射和类。
除非另有说明,本网站上的文档反映的是 Dart 3.6.0 版本。页面上次更新时间为 2024-02-07。 查看源代码 或 报告问题。