Dart中late、final

1,091 阅读4分钟

在Dart语言中,late关键字是Dart 2.12及更高版本中引入的一个特性,用于延迟初始化。它主要用于两种场景:非空类型的延迟初始化和显式的懒加载。

非空类型的延迟初始化

在引入空安全特性之后,Dart要求所有的变量在使用前都必须初始化。然而,在某些情况下,我们可能无法在声明变量的同时初始化它,比如依赖于构造函数参数或者需要进行异步操作来获取初始值。这时,late关键字就派上了用场。通过late标记的变量,Dart允许你稍后初始化这个变量,同时确保在第一次使用前已被初始化,否则会抛出异常。

class MyClass {
  late String description;

  void setDescription(String desc) {
    description = desc;
  }
}

显式的懒加载

late还可用于变量的懒加载,即变量在第一次被访问时才进行初始化。这对于初始化开销较大的变量非常有用,可以在确实需要这些变量的时候才去创建它们,从而提高程序的性能。

class MyDatabase {
  late final HeavyDatabase _database = HeavyDatabase();

  HeavyDatabase get database => _database;
}

在这个例子中,_database变量只会在第一次访问database属性时被初始化,而不是在MyDatabase类的实例被创建时。

注意事项

  • 使用late时需要小心,因为如果在变量被正确初始化之前访问它,会抛出LateInitializationError异常。
  • late不应该被用作绕过空安全的手段。确保在第一次访问变量之前已经对其进行了初始化。
  • 对于懒加载的场景,考虑初始化开销和访问频率,决定是否使用late是一个好的选择。

详细介绍Dart中的final

在 Dart 语言中,final 关键字用于声明一个变量,其值只能被赋值一次,并且在初始化后不允许被修改。final 可以用于各种类型的变量,包括基本数据类型、对象、集合等。使用 final 声明的变量必须在声明时或构造函数中初始化。final 关键字提供了一种不变性保证,有助于编写更安全、更可预测的代码。

final 的特性

  1. 一次赋值final 变量在初始化后,其值就固定了,不能被再次赋值。
  2. 编译时常量:如果 final 变量在编译时就能确定其值,那么可以将其视为编译时常量。这通常对基本数据类型和编译时常量表达式有效。
  3. 运行时初始化:如果 final 变量的值取决于运行时计算的结果,那么其值将在第一次使用时确定。
  4. 类级别的不变性:在类中使用 final 关键字可以确保实例变量在对象构造后不会改变。

final 与 const 的区别

final 和 const 都用于声明不可变的变量,但它们之间存在一些关键区别:

  • 初始化时机final 变量只能被赋值一次,并且可以在运行时被初始化。而 const 变量必须在编译时就确定其值。
  • 内存分配:每次使用 const 声明的变量时,Dart 都会重用相同的内存位置(如果值相同)。对于 final 变量,每个实例都可能占用不同的内存空间,除非它们是编译时常量。

使用场景

  • 不变的配置数据:使用 final 存储应用程序中不会改变的配置数据。
  • 单次赋值的运行时数据:当你需要存储在运行时确定且不会改变的数据时,使用 final
  • 类中的不可变属性:为了确保对象创建后某些属性不会改变,可以将类的实例变量声明为 final

示例

final String name = 'John Doe';
final int age;

class Person {
  final String id;
  final String name;

  Person(this.id, this.name);
}

void main() {
  // 正确:在构造函数中初始化 final 变量
  final person = Person('123', 'Alice');

  // 错误:final 变量不能被重新赋值
  // name = 'Jane Doe';
}

final 关键字在 Dart 中是一个非常有用的特性,它不仅可以帮助你编写更安全的代码,而且还可以向读者清晰地表明变量的意图。