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

Dart中const构造函数前加const的行为差异及final列表疑问

Dart中const构造函数的行为差异与final字段的疑问解答

两段代码行为差异的原因

第一段代码:

class Person{
  final List<String> names;
  
  const Person(this.names);
}

void main() {
  final Person person = Person(["Livia", "Lima"]);
  
  print(person.names);
  
  person.names.add("Carolina");
  
  print(person.names);
}

运行结果:

["Livia", "Lima"]
["Livia", "Lima", "Carolina"]

第二段代码:

class Person{
  final List<String> names;
  
  const Person(this.names);
}

void main() {
  final Person person = const Person(["Livia", "Lima"]);
  
  print(person.names);
  
  person.names.add("Carolina");
  
  print(person.names);
}

运行报错:

Unsupported operation: add

差异的核心在于构造函数调用时是否加const,决定了创建的实例类型:

  • 第一段代码里,Person(["Livia", "Lima"])未加const,即便构造函数是const类型,此时创建的是运行时普通Person实例。传入的["Livia", "Lima"]是常规可变List,因此后续可以通过add修改列表内容。
  • 第二段代码里,const Person(["Livia", "Lima"])明确使用const,创建的是编译时常量Person实例。在const上下文里,所有字面量对象(包括这里的列表)会自动转为不可变的const List,这类列表不支持修改操作,调用add就会抛出错误。

至于Effective Dart提到的“不要冗余使用const”,指的是在已处于const上下文(比如const集合内部)时,构造函数前的const可省略,但直接调用const构造函数时不加const,本质是创建普通实例,不属于冗余场景,二者是完全不同的用法。

关于final列表的疑问

final修饰的是变量的引用,而非变量指向的对象本身:

  • final List<String> names的含义是,names字段一旦赋值,就不能再指向其他List对象(比如不能执行person.names = ["new name"])。
  • 但names指向的List是否可变,由List自身类型决定:常规List(如["a", "b"]创建的)是可变的;const List(如const ["a", "b"]创建的)是不可变的。

所以第一段代码里的names是可变List,能添加元素;第二段里的names是const不可变List,无法修改。


内容的提问来源于stack exchange,提问作者Lívia Carolina

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 19:30:07