欢迎光临
我们一直在努力

【Flutter for OpenHarmony--Dart 入门日记】第2篇:常量声明详解——`const` 与 `final` 到底有什么区别?


【Dart 入门日记】第2篇:常量声明详解——const 与 final 到底有什么区别?

作者:灰灰勇闯IT 时间:2026年1月 系列定位:零基础记录 Dart 学习过程,适合编程新手、Flutter 初学者 本文重点:深入理解 const(编译时常量)与 final(运行时常量)的使用场景与本质区别

目录

  • 1. 为什么需要常量?
  • 2. const:编译期就确定的“绝对不变”值
    • 2.1 场景引入:圆周率 π 不可更改
    • 2.2 const 基本语法与代码示例
    • 2.3 ❌ 常见错误:const 表达式中不能包含变量
  • 3. final:运行时才确定的“一次赋值”变量
    • 3.1 场景引入:获取当前时间作为唯一操作时间戳
    • 3.2 final 基本语法与代码示例
  • 4. 核心对比:const vs final —— 编译时 vs 运行时
  • 5. 深入理解:为什么 Dart 要区分这两种常量?
  • 6. 实战建议:什么时候用 const,什么时候用 final?
  • 7. 常见误区与调试技巧
  • 8. 小结 & 下期预告

1. 为什么需要常量?

在编程中,有些值从诞生起就不该被修改。比如:

  • 数学常数:π(3.14159…)、e(2.718…)
  • 配置项:API 地址、版本号
  • 时间戳:用户点击按钮的精确时刻

如果这些值被意外修改,程序逻辑就会出错。因此,Dart 提供了两种“不可变”机制:const 和 final。

🌟 我的思考: 昨天学了 var,今天学“不能变的变量”,感觉像是在给数据上锁——有的锁在写代码时就焊死了(const),有的锁在程序跑起来那一刻才扣上(final)。


2. const:编译期就确定的“绝对不变”值

2.1 场景引入:圆周率 π 不可更改

计算圆的周长公式是:C = 2 × π × r。 其中,π 是一个数学常数,永远不变。这种值就应该用 const 声明。

2.2 const 基本语法与代码示例

语法:

const 常量名 =;

示例:计算半径为 5 的圆的周长

void main() {
const pi = 3.1415926; // 编译时常量
var radius = 5.0;
var circumference = 2 * pi * radius;
print('半径为 $radius 的圆,周长是 $circumference');
}

输出:

半径为 5.0 的圆,周长是 31.415926

!![[图片:932ad3c1d3ac4d22b724ccacb0101011.png](图:使用  声明 π 并成功计算周长)](https://i-blog.csdnimg.cn/direct/932ad3c1d3ac4d22b724ccacb0101011.png#pic_center)

✅ 特点:

  • 值在编译时就必须确定
  • 所有 const 对象在内存中是单例(相同值只存一份)
  • 可用于注解、元数据等需要编译期常量的场景

2.3 ❌ 常见错误:const 表达式中不能包含变量

const 的值必须是“字面量”或由其他 const 组成的表达式,不能依赖运行时才能知道的变量。

错误示例:

void main() {
var radius = 5.0;
// ❌ 错误!radius 是变量,无法在编译时确定
const area = 3.1415926 * radius * radius;
}

报错信息类似:

Error: Constant expressions can't refer to non-constant variables.

[图片:2344a96146ab4fdbb514d84dd8824ab8.png](图:尝试在  中使用变量导致编译错误)

💡 正确做法:改用 final,或者把整个表达式移到运行时计算。


3. final:运行时才确定的“一次赋值”变量

3.1 场景引入:获取当前时间作为唯一操作时间戳

假设我们要记录用户点击按钮的精确时间。这个时间只有在程序运行到那一行代码时才能知道,但它一旦获取,就不应再变。

这就是 final 的典型用武之地。

3.2 final 基本语法与代码示例

语法:

final 变量名 =;

示例:获取当前年份

import 'dart:core';

void main() {
final now = DateTime.now(); // 运行时获取当前时间
final currentYear = now.year;
print('当前年份是:$currentYear');
}

输出(假设今天是 2026 年):

当前年份是:2026

[图片:623f25a2821742c1a5ab2c6639278536.png](图:使用  获取当前时间并输出年份)

✅ 特点:

  • 值在运行时第一次赋值后锁定
  • 可以使用变量、函数返回值等动态内容初始化
  • 每次运行程序,final 的值可能不同(如时间、随机数)

4. 核心对比:const vs final —— 编译时 vs 运行时

特性constfinal
初始化时机 编译时 运行时
值是否可变 绝对不可变 初始化后不可变
能否使用变量初始化 ❌ 不行 ✅ 可以
内存优化 相同值共享同一对象(单例) 每次创建新对象
适用场景 数学常量、配置字面量 时间、用户输入、API 返回值

代码对比示例:

void main() {
// ✅ const:编译期确定
const pi = 3.1415926;
const appName = "My Flutter App";

// ✅ final:运行期确定
final timestamp = DateTime.now().millisecondsSinceEpoch;
final randomId = DateTime.now().microsecondsSinceEpoch % 1000;

print('App: $appName, π ≈ $pi');
print('时间戳: $timestamp, 随机ID: $randomId');
}


5. 深入理解:为什么 Dart 要区分这两种常量?

这背后是 性能 与 灵活性 的权衡:

  • const 用于极致优化 因为值在编译时已知,Dart 可以:

    • 将相同 const 对象合并(节省内存)
    • 在 AOT 编译(如 Flutter Release 模式)中直接内联值
    • 支持用作 Widget 构造函数的 const 参数(提升 UI 渲染性能)
  • final 保证运行时安全 当值依赖外部输入(如网络、传感器、时间),final 确保“只读一次”,防止后续逻辑意外修改。

📌 Flutter 开发提示: 在构建 Widget 时,尽量用 const 修饰那些不会变的子组件,例如:

const Text('欢迎来到我的 App', style: TextStyle(fontSize: 18));

这能显著减少重建开销!


6. 实战建议:什么时候用 const,什么时候用 final?

✅ 用 const 当:

  • 值是字面量(数字、字符串、布尔值)
  • 值由其他 const 组合而成
  • 用于配置、枚举、UI 静态文本

const double gravity = 9.8;
const List<String> weekdays = ['Mon', 'Tue', 'Wed'];

✅ 用 final 当:

  • 值来自函数调用(如 DateTime.now())
  • 值来自参数或用户输入
  • 值在构造函数中初始化(类成员)

class User {
final String name;
final int loginTime;

User(this.name) : loginTime = DateTime.now().millisecondsSinceEpoch;
}


7. 常见误区与调试技巧

❌ 误区1:“final 和 const 一样,都是常量”

→ 不完全对!final 是运行时常量,const 是编译时常量,性能和使用限制完全不同。

❌ 误区2:“const 可以放在函数里动态计算”

→ 不行!const 必须在编译时就能算出结果。

✅ 调试技巧:

  • 在 VS Code 中,悬停 const 变量会显示 “compile-time constant”
  • 尝试给 const 赋变量值,编译器会立即报错,这是好事!
  • 在 Flutter 中,开启 “Performance Overlay” 可观察 const Widget 是否被跳过重建

8. 小结 & 下期预告

✅ 本篇收获:

  • 掌握了 const 的使用:适用于编译期已知的绝对常量(如 π)
  • 理解了 final 的价值:适用于运行时确定但后续不变的数据(如时间戳)
  • 明确了二者的核心区别:编译时 vs 运行时
  • 避开了“在 const 中使用变量”的经典错误

🎯 动手练习: 尝试写一个 Circle 类,用 const 存储 π,用 final 存储半径,并提供计算面积和周长的方法。


➡️ 下期预告: 《【Dart 入门日记】第3篇:Dart 的基础数据类型全解析——int、double、String、bool 与 null 安全》 我们将系统学习每一种内置类型,并揭开 Dart 空安全(Null Safety)的神秘面纱!


💬 互动时间: 你在项目中更常用 const 还是 final?有没有因为混淆两者而踩过坑?欢迎在评论区分享你的故事!如果你觉得这篇文章帮你理清了概念,别忘了 点赞 + 收藏 + 关注,你的支持是我持续更新的最大动力!


📎 附:所有代码均可直接运行 环境要求:Dart SDK 3.0+,推荐使用 VS Code + Dart/Flutter 插件


赞(0)
未经允许不得转载:171主机测评 » 【Flutter for OpenHarmony--Dart 入门日记】第2篇:常量声明详解——`const` 与 `final` 到底有什么区别?
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址