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
相关产品推荐
相关产品推荐

