You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Dart中reference type、value type、canonicalized的具体定义咨询

Dart 内置类型相关术语说明

术语来源与定义

Dart官方没有针对reference type、immutable、canonicalized这三个术语做Dart专属的自定义解释,三者都是编程语言理论领域的通用概念,并非JavaScript、Swift或某一门特定语言的独有设计,学习Dart不需要提前掌握其他语言的对应概念,直接结合Dart的行为理解通用定义即可:

  • reference type(引用类型):指变量存储的是对象实例的内存引用,而非对象本身的完整数据拷贝,Dart中所有类型都符合这一特征,所有变量本质上都指向一个类的实例对象。
  • immutable(不可变):指对象实例一旦创建完成,其内部所有状态、属性都无法被修改,任何看似“修改”该对象的操作,本质都是生成并返回一个全新的对象实例,不会改动原对象的任何内容。
  • canonicalized(实例规范化):指对于同类型、值相等的不可变对象,编译器或运行时会全局仅维护一份唯一实例,不会重复创建多个值完全相同的冗余对象。

canonicalized的实际含义与代码现象解释

首先明确:canonicalized不等同于“值是const常量”,你贴出的测试代码运行后outer值不变的现象,和canonicalized特性没有直接关系,是引用类型赋值规则+int不可变两个特性共同导致的:

void main() {
  int outer = 0;
  int other = outer;
  other = 1;
  print(outer); // 0 (not changed)
}

上述代码中,int other = outer只是把outer存储的、指向值为0的int实例的引用拷贝了一份给other变量;后续other = 1的操作,本质是修改other变量存储的引用,让它指向值为1的int实例,全程没有对值为0的原int对象做任何修改——哪怕int没有做canonicalized处理,只要它满足不可变的特性,这段代码的输出结果依然是0,这个用例无法验证canonicalized特性。

Dart中对int、double、String、bool做canonicalized处理的实际表现是:只要这几类对象的值相等,无论实例是编译期const生成,还是运行时计算生成,都会指向全局唯一的同一份实例。可以用identical方法验证:

void main() {
  const int a = 2;
  const int b = 1 + 1;
  print(identical(a, b)); // true,const常量默认做规范化
  
  int c = 2;
  int d = 1 + 1; // 运行时计算得到值2
  print(identical(c, d)); // 同样为true,普通声明的int只要值相等就指向同一份实例
}

作为对比,普通的自定义不可变类,只有const声明的实例会被规范化,非const生成的同值实例是不同对象:

class ImmutablePoint {
  final int x, y;
  const ImmutablePoint(this.x, this.y);
}

void main() {
  const p1 = ImmutablePoint(1, 2);
  const p2 = ImmutablePoint(1, 2);
  print(identical(p1, p2)); // true,const常量规范化

  var p3 = ImmutablePoint(1, 2);
  var p4 = ImmutablePoint(1, 2);
  print(identical(p3, p4)); // false,非const创建的同值实例不会自动规范化
}

正是因为int、double、String、bool同时满足不可变+实例规范化两个特征,它们虽然本质是引用类型,使用时却完全不会出现普通引用类型的副作用,表现和值类型完全一致。

内容的提问来源于stack exchange,提问作者森口万太郎

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 17:57:19