字
字节笔记本
2026年3月22日
Dart 中 static、final、const 关键字详解
这篇文章将详细介绍 Dart 语言中 static、final、const 三个关键字的区别和使用场景,帮助开发者在实际编码中正确选择合适的关键字来声明变量。
基本概念
在 Dart 开发中,const、final、static 这三个关键字经常让人困惑。本文从基本概念、使用要点和场景选择三个方面进行总结。
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成员属于类而非实例
三者对比
| 特性 | const | final | static |
|---|---|---|---|
| 值的确定时机 | 编译时 | 运行时 | 声明时 |
| 是否可变 | 不可变 | 不可变(赋值后) | 可变 |
| 类成员使用 | 需要 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); // 编译错误
}分享: