以下代码编译并运行良好:
void testFinal() {
for (var i = 0; i < 10; i++) {
final x = i + 1;
print(x);
}
}
所以似乎最终的注释&#34;重新应用&#34;每次循环。这似乎与final的动机不一致,(I type-infer)是允许编译器更好地保证某些代码转换。我们是否将循环视为一堆展开的独立范围?
答案 0 :(得分:3)
所有块都有自己的范围:
void main() {
if (true)
{
final x = 0;
}
final x = 10; //ok
}
没有工作:
void main() {
final x = 0;
for (var i = 0; i < 10; i++) {
x = i + 1; //NoSuchMethodError: cannot assign to final variable 'x'
print(x);
}
}
但是这个会:
void main() {
final x = 0;
for (var i = 0; i < 10; i++) {
final x = i + 1; //ok again
print(x);
}
}
因为你说的每次迭代&#34;我想要一个新的最终x&#34;
他们是区级决赛,每次都是新的宣言。因为那些是决赛,而不是静力学 - 它是预期的行为。至少,它们可以帮助您避免一些错误,并提供代码注释,基本上说:&#34;不会改变&#34;。
答案 1 :(得分:3)
简而言之:是的。
每个区块都是自己的范围。每次执行块时,它都会在块中创建变量的新实例。
“final”变量只能初始化一次,但每次“执行”声明时,都会创建一个新的不可修改的变量。块是仅仅是一个简单的嵌套块,还是一个循环体,甚至是一个函数体并不重要。
main() {
foo(1);
foo(2);
}
void foo(final parameter) {
final local = parameter * 2;
for (final i in [1, 2]) {
final block1 = local + i;
{
final block2 = local + i * 2;
print(parameter * local * block1 * block2);
}
}
}
在此示例中,所有最终变量在程序的生命周期内都会使用多个值。每次执行最终声明时,变量都会通过值引入范围,当退出块/范围时,变量将不再存在。
for(final i in ...)
是专门处理的,因此每次循环迭代也会创建一次i
变量。