Dart 中的 const
和 final
关键字有什么区别?
const
的一些详细信息:stackoverflow.com/questions/51576209/… 和对 final
的简单解释是常量(一旦使用 final 关键字创建就不能重新分配或分配),您必须对其进行一次初始化。
There is a post on dart's website and it explains it pretty well.
最后:
“final” 表示单一赋值:final 变量或字段必须有一个初始化器。一旦分配了一个值,最终变量的值就不能更改。 final 修改变量。
常数:
“const”在 Dart 中具有更复杂和微妙的含义。 const 修改值。您可以在创建集合时使用它,例如 const [1, 2, 3],以及在构造对象(而不是 new)时,例如 const Point(2, 3)。在这里,const 意味着对象的整个深度状态可以完全在编译时确定,并且对象将被冻结并且完全不可变。
const 对象有几个有趣的属性和限制:
它们必须由可在编译时计算的数据创建。 const 对象无权访问您在运行时需要计算的任何内容。 1 + 2 是有效的 const 表达式,但 new DateTime.now() 不是。
它们是深刻的、传递性的不可变的。如果您有一个包含集合的最终字段,则该集合仍然可以是可变的。如果您有一个 const 集合,则其中的所有内容也必须是 const 递归的。
它们是规范化的。这有点像字符串实习:对于任何给定的 const 值,无论 const 表达式被计算多少次,都将创建并重用一个 const 对象。
那么这是什么意思?
Const:
如果您拥有的值是在运行时计算的(例如 new DateTime.now()
),您可以不对其使用 const。但是,如果值在编译时已知 (const a = 1;
),那么您应该使用 const
而不是 final
。 const
和 final
之间还有 2 个其他较大的区别。首先,如果您在类中使用 const
,则必须将其声明为 static const
而不仅仅是 const
。其次,如果您有一个 const
集合,那么其中的所有内容都在 const
中。如果您有一个 final
集合,那么其中的所有内容都不是 final
。
Final:
如果您在编译时不知道该值,则应在 const
上使用 final
,它将在运行时计算/获取。如果您想要一个无法更改的 HTTP 响应,如果您想要从数据库中获取某些内容,或者如果您想要从本地文件中读取,请使用 final
。任何在编译时未知的东西都应该是 final
超过 const
。
综上所述,const
和 final
都不能重新分配,但 final
对象中的字段,只要它们本身不是 const
或 final
,就可以重新分配(不像 { 1})。
常量
值必须在编译时已知,const birthday = "2008/12/25"
初始化后无法更改。
最后
值必须在运行时已知,final birthday = getBirthDateFromDB()
初始化后无法更改。
final
变量不能重新分配,但对象可以改变。
final
对象无法修改,但其字段可以更改。 dartpad.dartlang.org/?id=2078935ac3ac4fcb26e8f8e53b250889
合并@Meyi 和@faisal-naseer 的答案并与少量编程进行比较。
常量:
const 关键字用于使变量存储编译时常量值。编译时间常数值是一个在编译时将保持不变的值:-)
例如 5
是一个编译时间常数。而 DateTime.now()
不是编译时间常数。因为此方法将在运行时返回行执行的时间。所以我们不能将 DateTime.now()
分配给 const
变量。
const a = 5;
// Uncommenting below statement will cause compile time error.
// Because we can't able to assign a runtime value to a const variable
// const b = DateTime.now();
应该在同一行初始化。
const a = 5;
// Uncommenting below 2 statement will cause compilation error.
// Because const variable must be initialized at the same line.
// const b;
// b = 6;
下面提到的所有陈述都是可以接受的。
// Without type or var
const a = 5;
// With a type
const int b = 5;
// With var
const var c = 6;
类级 const 变量应如下所示进行初始化。
Class A {
static const a = 5;
}
实例级 const 变量是不可能的。
Class A {
// Uncommenting below statement will give compilation error.
// Because const is not possible to be used with instance level
// variable.
// const a = 5;
}
const
的另一个主要用途是使 对象不可变。为了使类对象不可变,我们需要在构造函数中使用 const 关键字,并将所有字段设为 final,如下所述。
Class A {
final a, b;
const A(this.a, this.b);
}
void main () {
// There is no way to change a field of object once it's
// initialized.
const immutableObja = const A(5, 6);
// Uncommenting below statement will give compilation error.
// Because you are trying to reinitialize a const variable
// with other value
// immutableObja = const A(7, 9);
// But the below one is not the same. Because we are mentioning objA
// is a variable of a class A. Not const. So we can able to assign
// another object of class A to objA.
A objA = const A(8, 9);
// Below statement is acceptable.
objA = const A(10, 11);
}
我们可以对列表使用 const 关键字。
const a = const [] - 变量 a
初始化为 const
,其中包含 const
个对象的列表(即,该列表应仅包含编译时常量和不可变对象)。所以我们不能将 a
分配给另一个列表。
var a = const [] - 变量 a
初始化为 var
,其中包含列表 const
个对象。因此我们可以将另一个列表分配给变量 a
。
Class A {
final a, b;
const A(this.a, this.b);
}
class B {
B(){ // Doing something }
}
void main() {
const constantListOfInt = const [5, 6, 7,
// Uncommenting below statement give compilation error.
// Because we are trying to add a runtime value
// to a constant list
// DateTime.now().millisecondsSinceEpoch
];
const constantListOfConstantObjA = const [
A(5, 6),
A(55, 88),
A(100, 9),
];
// Uncommenting below 2 statements will give compilation error.
// Because we are trying to reinitialize with a new list.
// constantListOfInt = [8, 9, 10];
// constantListOfConstantObjA = const[A(55, 77)];
// But the following lines are little different. Because we are just
// trying to assign a list of constant values to a variable. Which
// is acceptable
var variableWithConstantList = const [5, 6, 7];
variableWithConstantList = const [10, 11, 15];
var variableOfConstantListOfObjA = const [A(5, 8), A(7, 9), A(10, 4)];
variableWithConstantList = const [A(9, 10)];
}
最后:
final 关键字也用于使变量保持一个常量值。初始化后,我们无法更改该值。
final a = 5;
// Uncommenting below statement will give compilation error.
// Because a is declared as final.
// a = 6;
下面提到的所有陈述都是可以接受的。
// Without type or var
final a = 5;
// With a type
final int b = 5;
// Can't use var along with final keyword. Uncommenting below line cause compilation issue.
// final var c = 6;
能够分配运行时值。
// DateTime.now() will return the time when the line is getting
// executed. Which is a runtime value.
final a = DateTime.now();
var b = 5;
final c = b;
类级别的最终变量必须在同一行中初始化。
Class A {
static final a = 5;
static final b = DateTime.now();
}
实例级别的最终变量必须在同一行或构造函数初始化中进行初始化。创建对象时,该值将被放入内存。
Class A {
final a = 5;
}
// Constructor with a parameter.
Class B {
final b;
B(this.b);
}
// Constructor with multiple parameter.
Class C {
final c;
C(this.c, int d) {
// Do something with d
}
}
void main() {
A objA = new A();
B objB = new B(5);
C objC = new C(5, 6);
}
分配列表。
final a = [5, 6, 7, 5.6, A()];
// Uncommenting Below statement will give compilation error.
// Because we are trying to reinitialize the object with another list.
// a = [9.9, 10, B()];
const immutableObja = const A(5, 6);
也可以写成 const immutableObja = A(5, 6);
,因为智能 Dart 编译器会选择 const A(5,6)
而不是 new A(5,6)
。
final var c = 6;
是不允许的。声明的成员不能同时声明为 final
和 var
。
由@Meyi 扩展答案
final 变量只能设置一次,并且在访问时被初始化。(例如,如果您只使用 maximumNumberOndice 的值,则从下面的代码部分中,该值将被初始化并分配内存)。
const 在本质上是内部最终的,但主要区别在于它的编译时间常数在编译期间被初始化,即使你不使用它的值,它也会被初始化并占用内存空间。
类中的变量可以是最终的,但不是常量,如果您想要类级别的常量,请将其设为静态常量。
代码:
void main() {
// final demonstration
final biggestNumberOndice = '6';
// biggestNumberOndice = '8'; // Throws an error for reinitialization
// const
const smallestNumberOnDice = 1;
}
class TestClass {
final biggestNumberOndice = '6';
//const smallestNumberOnDice = 1; //Throws an error
//Error . only static fields can be declared as constants.
static const smallestNumberOnDice = 1;
}
final
和 const
都防止变量被重新分配(类似于 final
在 Java 中的工作方式或 const
在 JavaScript 中的工作方式)。
区别与内存的分配方式有关。在运行时为 final
变量分配内存,在编译时为 const
变量分配内存。 final
修饰符应该是更常用的,因为许多程序变量不需要任何内存,因为程序逻辑不会调用它们来初始化它们。使用 const
变量,您基本上是在告诉计算机,“嘿,我需要预先存储这个变量的内存,因为我知道我会需要它。”
以这种方式思考它们可以更容易地理解它们在语法用法上的差异。主要是 final
变量可能是实例变量,但 const
必须是类上的 static
变量。这是因为实例变量是在运行时创建的,而 const
变量——根据定义——不是。因此,类上的 const
变量必须是 static
,这意味着该变量的单个副本存在于一个类上,而不管该类是否被实例化。
该视频非常简单地对其进行了分解:https://www.youtube.com/watch?v=9ZZL3iyf4Vk
本文更深入并解释了两者之间非常重要的语义差异,即 final
修改变量和 const
修改值,本质上归结为只能初始化可在编译时派生的 const
值 -时间。
https://news.dartlang.org/2012/06/const-static-final-oh-my.html
我的理解
const
表示它的初始值必须是固定的,不能是动态值;
final
表示它的初始值必须是固定的,但可以是动态值,等于 var
具有固定值。
代码演示
常量
void main() {
const sum = 1 + 2;
// ✅ const can not change its value
print("sum = ${sum}");
// ⚠️ Const variables must be initialized with a constant value.
const time = new DateTime.now();
// ❌ Error: New expression is not a constant expression.
print("time = ${time}");
}
最后
// new DateTime.now();
// dynamic timestamp
void main() {
final sum = 1 + 2;
// ✅ final can not change its value
print("sum = ${sum}");
final time = new DateTime.now();
// ✅ final === var with fixed value
print("time = ${time}");
}
截图
https://i.stack.imgur.com/AK3Jm.png
参考
https://dart.dev/guides/language/language-tour#final-and-const
dart 中的 final 和 const 令人困惑,我们认为它们是相同的。
https://i.stack.imgur.com/RmOxx.png
PS 我包含图像而不是文本,因为我无法轻松地将 Stackoverflow .md 格式的信息制成表格。
如果您来自 C++
,则 Dart
中的 const
是 C++
中的 constexpr
,而 Dart
中的 final
是 C++
中的 const
。
以上仅适用于原始类型。但是,在 Dart
中,标记为 final
的对象在其成员方面是可变的。
const
几乎总是用于指定对象不能通过特定的引用或指针来改变。 Dart 中的 final
不会阻止对象通过该变量进行变异。
需要 TLDR 的 TLDR 吗? :)
任何在编译时未知的东西都应该是 final
超过 const
。
我可以简明扼要地描述所有这些答案。
const list = [1, 2, 3];
变量/标识符和值都是常量。喜欢 - const list = const [1, 2, 3]
这就是为什么他们不允许被重新分配。
非常适合全局变量。
可以将其用作类变量,但必须设置为静态。像 - 静态常量列表 = [1, 2, 3]。
与:
final list = [1, 2, 3];
变量/标识符是 const 但值不是。喜欢 - const list = [1, 2, 3]
这就是为什么我们可以像 - list.add(4)
简单的话:
常量
值必须在编译时已知,即来自内部文件的值。
示例:API 密钥、应用程序支持的语言或 ie 帮助文件中的任何变量,基本上是应用程序附带的任何内容。
最后
值必须在运行时知道,可以是上面的数据,也可以是在应用程序启动时检查的设备信息,或者在应用程序启动时从 API 或服务器加载的数据,但在应用程序准备好之前使用即您需要检查用户是否登录,您的应用程序将加载或检查来自服务器的会话令牌。
https://i.stack.imgur.com/oiegJ.png
什么时候使用哪个关键字?
两者的一个简单示例: 使用 final:如果您不知道它在编译时的值是什么。例如,当您可能需要从 API 获取数据时,就会在运行代码时发生这种情况。
使用 const:如果您确定在运行代码时不会更改某个值。例如,当您声明一个始终保持不变的句子时。
https://itnext.io/difference-between-const-and-final-in-dart-78c129d0c573
const
是编译时常量。
final
是运行时常量。
final
变量不能重新分配,但对象可以变异。它们不是运行时常量。
您不能使用 final
初始化 const
。例如 :
final myConst = 1;
const myFinal = 2;
final a = myConst; // possible
final b = myFinal; // possible
const c = myConst; // this is not possible
const d = myFinal; // possible
const
和 final
的含义。此外,您将 const
对象命名为 myFinal
和 final
变量 myConst
非常令人困惑。
带有 final
关键字的变量将在运行时初始化,并且只能分配一次。
带有 const
关键字的变量在编译时初始化,并且在运行时已分配。
使用 final
:如果您在编译时不知道它的值是什么。例如,当您可能需要从 API 获取数据时,就会在运行代码时发生这种情况。使用 const
:如果您确定在运行代码时不会更改某个值。例如,当您声明一个始终保持不变的句子时。
不定期副业成功案例分享
void main() { var fruits = ['apples', 'bananas', 'oranges']; for ( final fruit in fruits) { print('I like to eat $fruit'); } }
它会打印总是一样的吗?