const和final来修饰属性field都表示对象不可变。但是const在编译期起到作用。而final则是在运行期起作用。
可以通过dart sdk源码中提供的dump_kernel工具来更深刻地认识一下。
dart编译的过程,会先扫描dart文件,生成ast树,然后生成dart intermidate language file即 app.dill,然后根据aot或者jit生成不同的产物。可以看一下const在ast转换成dil文件后,产物中的形态。
static const field asy::StreamTransformer<core::Object, res10::Result<core::Object>> captureStreamTransformer = #C15926;
static const field asy::StreamTransformer<res10::Result<core::Object>, core::Object> releaseStreamTransformer = #C15927;
static const field str17::StreamSinkTransformer<core::Object, res10::Result<core::Object>> captureSinkTransformer = #C15928;
static const field str17::StreamSinkTransformer<res10::Result<core::Object>, core::Object> releaseSinkTransformer = #C15929;
比如这是某个类的dil在dump_kernel后的产物中的形态。可以看到const修饰的变量转换成了 [#C数字]开头的形式。
里面有个常量区域,其中放的全是这些常量符号。
可以看到const修饰的常量,compile的时候就已经做了转换
可以看到指向cap2::中的用const修饰的constuctor构造函数。
我们再看一下final修饰的变量,用关键字final搜索。
没有看到特殊的处理。
const A a = A(),此时A的构造函数必须要有const修饰,如果没有,那么ast dump到二进制dill文件的过程中ConstantsTransformer会报错。
含有code example的解释见如下链接。
Dart – Const And Final Keyword
为什么要这样设计呢?
思考一番。会发现constant池子里的对象可以被所有这些static const共用,这样节省了内存和dill的体积。