Dart 变量

  • Dart 变量体系主要是围绕着 空安全 不可变性 初始化时机 进行设计的讷

  • 核心的关键字有 var final const late dynamic 以及 类型注解

Dart 空安全

  • 编译器强制检查变量是否可为 nullable ,避免运行时空指针的异常出现吧

  • 两类

    • 可空类型:类型后加 ? 实现可控类型的定义

    • 非空类型:默认是非空的,也就是在定义的时候不会出现 ?

  • 优化价值

    • 消除的是运行时出现的风险,减少调试成本

String name = "hello world";
String? name;

Dart var 关键字

  • 定义的是动态类型的数据,编译器实现对应的动态的推导数据的类型吧

  • 优化价值

    • 类型注解实现让编译器提前明确变量类型,可做静态类型检查和编译期优化

    • var 虽然是动态类型的,保持了灵活,但是编译器在编译器实现固化类型(运行时无类型开销吧)

Dart late关键字

  • 声明的变量延迟初始化,以及变量在首次使用时才会初始,非声明时

  • 优化价值

    • 适合于资源密集型对象(大内存数据或者网络请求结果)

    • 避免声明时过早初始化导致的性能浪费

    • 也可以用于解决循环依赖场景的解决

Dart final和const

  • final 变量实现的是只赋值一次,运行时确定值(获取得到网络请求的配置吧)

  • const 编译期常量,值必须是编译期可确定的字面量或者构造函数

Dart dynamic 动态类型

  • 变量类型完全动态,编译期不做类型检查,运行时解析

优化维度

技术原理

示例效果

编译期优化

类型注解让编译器提前做静态分析,消除冗余检查;const 触发常量折叠、内联。

const color = Color(red: 255); 编译期直接替换为内存地址,运行时无需构造。

运行时优化

不可变变量(final/const)无需做线程同步;late 延迟初始化减少启动耗时。

多线程场景下 final 变量无竞态风险,省去锁开销。

内存优化

const 变量内存复用(相同值只存一份);late 避免过早分配大对象内存。

100 个 const int a = 1; 仅占用一份 int 内存。

维度

final

const

赋值时机

运行时确定值(如从网络、数据库获取的值)

编译期确定值(必须是字面量或 const 构造的对象)

内存表现

运行时分配内存,相同值可能存多份

编译期常量池复用,相同 const 值只存一份

使用场景

运行时确定的不可变数据(如用户配置、网络结果)

编译期确定的固定值(如常量、主题色、数学常量)

语法限制

可在构造函数中赋值,或延迟初始化(结合 late

必须在声明时赋值,且值必须是编译期可计算的

核心需要注意的是:我们的 final 和 const 对应的运行时和编译时的确定值的操作吧

场景类型

是否用 final

原因

实例创建后值永久不变

✅ 推荐用 final

保证不可变性,避免逻辑错误,且编译器可做优化。

实例生命周期内会修改

❌ 不用 final

用可变变量(var/ 显式类型),支持业务逻辑的状态变更。

延迟初始化但后续不变

✅ 用 late final

结合 late 延迟初始化,同时保证后续不可变(如一次性加载的配置)。

延迟初始化且后续会变

❌ 用 late(不加 final)

仅延迟初始化,后续允许修改。

class DataLoader {
  late List<String> data; // 延迟加载,但加载后可能被更新

  Future<void> loadData() async {
    data = await fetchDataFromServer();
  }

  void refreshData() async {
    data = await fetchDataFromServer(); // 允许修改,所以不用final
  }
}

Dart 数据类型

  • 核心就是基础数据类型

  • Records 类型

  • 集合类型

  • 泛型

  • 别名

  • 异步编程

  • Feature

  • Stream

  • 和其他语言的交互调用 swift kotlin javascript wasm

  • 工程化 monorepo

  • package 的自定义实现吧pubspec 配置文件自定义吧