字节笔记本

2026年3月22日

Dart 中 static、final、const 关键字详解

这篇文章将详细介绍 Dart 语言中 static、final、const 三个关键字的区别和使用场景,帮助开发者在实际编码中正确选择合适的关键字来声明变量。

基本概念

在 Dart 开发中,constfinalstatic 这三个关键字经常让人困惑。本文从基本概念、使用要点和场景选择三个方面进行总结。

const

const 用来声明编译时常量,一旦赋值就不允许修改。

用在等号左边——声明变量

dart
void main() {
  const a = 1;
  const b = 'hello';
  const c = a; // 引用其他 const 变量
}

编译时常数包括以下几种场景:

  • 数值、字符串、其他 const 变量
  • 表达式,表达式的所有值都是编译时可知的:
dart
const a = 1;
const b = a > 1 ? 2 : 1;
  • 集合或对象,集合必须用 const 修饰,对象构造函数必须用 const 修饰:
dart
const a = const [1, 2, 3];
const b = ConstObject(2);

用在等号右边——修饰值

const 修饰值意味着对象的整个深度状态可以在编译时完全确定,对象将被冻结并且完全不可变。

dart
// 错误:集合元素必须是编译时常数
var c = 2;
var a = const [c, 2, 3];

// 错误:不允许修改 const 集合
const a = const [1, 2, 3];
a[1] = 2;

修饰类的构造函数

const 修饰构造函数时,该类的所有成员必须是 final 的:

dart
class ConstObject {
  final value;
  // 错误:const 构造函数中只能有 final 成员
  // int value2;

  const ConstObject(this.value);

  log() {
    print(value);
  }
}

const 要点

  • 声明类成员变量时,const 变量必须同时被声明为 static
  • const 变量命名应使用全大写加下划线
  • const 变量只能在定义时初始化

final

final 要求声明的变量在赋值之后不再改变,但不要求赋值的是编译时常数

dart
final name = fetchData(); // 运行时确定的值也可以
name = 'new'; // 错误:final 变量不能重新赋值

两种使用场景

  • 文件中的变量声明:必须在声明时赋值
  • 类的成员变量声明:可以在声明时赋值,也可以通过构造函数赋值
dart
class Person {
  final String name;
  final int age;

  // 通过构造函数语法糖赋值
  Person(this.name, this.age);

  // 通过初始化列表赋值
  Person.fromJson(Map json)
      : name = json['name'],
        age = json['age'];
}

final 要点

  • final 变量可以在构造函数参数列表或初始化列表中初始化
  • final 变量的值可以在运行时确定

static

static 声明类的静态成员,使得多个对象共享同一个成员变量实例。

dart
class Counter {
  static int count = 0;

  Counter() {
    count++;
  }
}

void main() {
  var a = Counter();
  var b = Counter();
  print(Counter.count); // 2
}

static 要点

  • 在文件中,变量不能声明为 static
  • static 成员属于类而非实例

三者对比

特性constfinalstatic
值的确定时机编译时运行时声明时
是否可变不可变不可变(赋值后)可变
类成员使用需要 static const可单独使用需配合 final/const
运行时赋值不允许允许允许
相同参数实例同一实例不同实例N/A

场景选择指南

类成员选择

判断顺序关键词
值是编译时常数static const
值不是编译时常数,但所有对象共享static final(确定不变);static(可能变化)
各对象持有不同实例,但只能赋值一次final
其它普通定义
dart
class AppConfig {
  // 编译时常量——所有类共享
  static const String APP_NAME = 'MyApp';
  static const int MAX_RETRY = 3;

  // 运行时确定——所有类共享,不再改变
  static final String version = _getVersion();

  // 各对象不同,但赋值后不变
  final String id;
  final DateTime createdAt;

  AppConfig(this.id) : createdAt = DateTime.now();
}

文件级变量选择

判断条件关键词
常量const
非常量,但在声明时确定且不改变final
其它普通定义
dart
// 文件级
const API_URL = 'https://api.example.com'; // const
final database = initDatabase();           // final
var count = 0;                             // 普通变量

常见错误

dart
// 错误 1:const 变量引用非 const 值
var x = 1;
const y = x; // 编译错误

// 正确
const x = 1;
const y = x; // OK

// 错误 2:final 变量重新赋值
final list = [1, 2, 3];
list = [4, 5, 6]; // 编译错误

// 注意:final 集合的内容可以修改!
final list = [1, 2, 3];
list.add(4); // OK,修改的是集合内容而非变量引用
list[0] = 10; // OK

// 如果需要不可变集合,使用 const
const list = [1, 2, 3];
list.add(4); // 运行时错误

// 错误 3:const 构造函数中包含非 final 成员
class Bad {
  int value; // 应该是 final
  const Bad(this.value); // 编译错误
}
分享: