我无法在常量列表和不可修改列表中添加/删除/修改元素。那么,如果两者都在做同样的事情,它们之间有什么区别呢?
没有区别,因为稍微夸张一点,没有"const列表";。
在Dart中,常量不是值的属性,而是表达式的属性。
示例:
class Foo {
final int x;
const Foo(this.x);
}
main() {
var foo1 = const Foo(1);
var foo2 = new Foo(1);
print(isConstant(foo1)); // cannot be done.
}
没有办法编写一个通用的isConstant
函数来区分使用const
创建的对象和使用new
创建的对象。运行时系统在某个地方有一个const创建的对象列表(因为它需要它来将另一个const Foo(1)
规范化为相同的值(,但值本身不知道它是使用const
表达式创建的。
列表文字与基于构造函数的对象创建略有不同,因为非常量文字是可变的,而常量文字不是。相反,const
文字会创建一个列表对象,类似于使用List.unmodifiable
创建的列表对象。同样,列表对象本身不知道它是使用const [...]
还是List.unmodifiable([...])
创建的,它只知道它是一个具有特定值集的不可修改列表。
虚拟机实际上对const列表和不可修改列表都使用相同的类(dart2js对所有内容都使用JS Array,但确实以相同的方式将它们标记为固定长度和不可更改(。编译器不必使用同一个类,const
列表是如何实现的,这是一个实现细节,但它们只有一个不可修改列表的实现也就不足为奇了,其他任何事情都会浪费。
因此,const列表对象和使用List.unmodifiable
创建的列表之间没有区别。它们是同一实现类的实例。
(显然,包含常量列表的常量变量可以在其他常量表达式中使用,并且常量列表文本是规范化的,所以如果在程序中的两个位置写入const [1]
,它的计算结果是相同的列表对象,但对象本身只是一个不可修改的列表(。
这是有区别的。将const
用于List
时,只能添加常数值。然而,不可修改列表的情况并非如此。
var foo = 1;
const l1 = [foo]; // Compile-time error
final l2 = List.unmodifiable([foo]); // No error
另一个重要区别是两个相等的const
对象保证是相同的(因此它们指向相同的内部对象,因为对象是在编译时构建的(,其中两个不可修改的列表将始终是两个不同的对象:
void main() {
final unmodifiableList1 = List<int>.unmodifiable(<int>[1,2,3]);
final unmodifiableList2 = List<int>.unmodifiable(<int>[1,2,3]);
print(identical(unmodifiableList1, unmodifiableList2)); // false
const constList1 = [1,2,3];
const constList2 = [1,2,3];
print(identical(constList1, constList2)); // true
}