Dart中''const''和''final''关键字有什么区别?

时间:2018-05-20 02:02:51

标签: dart const keyword final

Dart中constfinal关键字有什么区别?

15 个答案:

答案 0 :(得分:47)

我在dart的网站上发现了这篇文章,它解释得非常好。

https://news.dartlang.org/2012/06/const-static-final-oh-my.html

决赛:

  

“final”表示单一赋值:最终变量或字段必须具有初始值设定项。一旦赋值,就不能改变最终变量的值。 final修改变量

常数:

  

“const”的含义在Dart中有点复杂和微妙。 const修改。您可以在创建集合时使用它,例如const [1,2,3],以及构造对象(而不是新的)时,如const Point(2,3)。这里,const意味着对象的整个深度状态可以在编译时完全确定,并且对象将被冻结并完全不可变。

     

Const对象有几个有趣的属性和限制:

     

必须根据可在编译时计算的数据创建它们。 const对象无法访问运行时需要计算的任何内容。 1 + 2是一个有效的const表达式,但新的DateTime.now()不是。

     

他们是深刻的,过渡性的一成不变的。如果您有包含集合的final字段,则该集合仍然可以变为可变。如果你有一个const集合,那么其中的所有东西也必须是递归的const。

     

他们规范化。这有点像字符串实习:对于任何给定的const值,无论const表达式被计算多少次,都会创建并重用一个const对象。

答案 1 :(得分:16)

巩固了@Meyi和@ faisal-naseer的答案,并与很少的编程比较。

const:

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;
// With var
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()];

答案 2 :(得分:13)

扩展@Meyi的答案

  • 最终变量只能设置一次,并在以下情况下初始化 (例如,如果仅使用biggestNumberOndice的值,则将在下面的代码部分中访问该值,然后将其初始化并分配内存)。
  • 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;
}

答案 3 :(得分:5)

dart中的

finalconst令人困惑,以至于我们认为两者相同。

让我们看看它们的区别:

P.S。我加入图片而不是文字,因为无法列出信息 轻松使用Stackoverflow .md格式。

答案 4 :(得分:2)

需要 TLDR 的 TLDR 吗? :)

任何在编译时未知的东西都应该是 final 超过 const

答案 5 :(得分:1)

finalconst都防止重新分配变量(类似于final在Java中的工作方式或const在JavaScript中的工作方式)。

差异与内存分配方式有关。在运行时为final变量分配内存,在编译时为const变量分配内存。 final修饰符应该更常用,因为许多程序变量将不需要任何内存,因为程序逻辑不会要求对其进行初始化。有了const变量,您基本上是在告诉计算机:“嘿,我需要该变量的内存,因为我知道我将需要它。”

以这种方式思考它们可以更轻松地理解其语法用法上的差异。主要是final变量可以是实例变量,但是const必须是类上的static变量。这是因为实例变量是在运行时创建的,而const变量(按定义)不是。因此,一个类上的const变量必须为static,这意味着该变量存在于一个类中,而无论该类是否被实例化。

此视频非常简单地将其分解为: https://www.youtube.com/watch?v=9ZZL3iyf4Vk

本文更深入地介绍了两者之间非常重要的语义区别,即final修改变量,而const修改值,这实际上归结为只能初始化{{1 }}在编译时派生的值。

https://news.dartlang.org/2012/06/const-static-final-oh-my.html

答案 6 :(得分:1)

我的理解

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}");
}

enter image description here enter image description here

裁判

https://dart.dev/guides/language/language-tour#final-and-const

答案 7 :(得分:0)

如果您来自C++,则const中的Dartconstexpr中的C++,而final中的Dartconst中的C++

以上内容仅适用于基本类型。 但是在Dart中标记为final的对象在其成员方面是可变的。

答案 8 :(得分:0)

Const

  

必须在 编译时 const birth = "2008/12/26"处知道值。   初始化后无法更改


最终

  

必须在 运行时 final birth = getBirthFromDB()处知道值。初始化后无法更改

答案 9 :(得分:0)

您无法使用const初始化final。例如:

  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

答案 10 :(得分:0)

何时使用哪个关键字?

两者的简单示例: 使用final:如果您不知道编译时的价值。例如,当您需要从API获取数据时,在运行代码时就会发生这种情况。

使用const:如果您确定在运行代码时不会更改值。例如,当您声明一个始终保持不变的句子时。

https://itnext.io/difference-between-const-and-final-in-dart-78c129d0c573

答案 11 :(得分:0)

const是一个编译时常量。

final是运行时常量。

答案 12 :(得分:0)

如果您从不打算更改变量,请使用 finalconst,代替 var 或与类型一起使用。 final 变量只能设置一次; const 变量是编译时常量。 (const 变量隐式为 final。)final 顶级变量或类变量在第一次使用时被初始化。

以下是创建和设置 final 变量的示例:

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';

您无法更改 final 变量的值:

name = 'Alice'; // Error: a final variable can only be set once.

const 用于要成为编译时常量的变量。如果 const 变量在类级别,请将其标记为 static const。在声明变量的地方,将值设置为编译时常量,例如数字或字符串文字、const 变量或对常量进行算术运算的结果:

const bar = 1000000; // Unit of pressure (dynes/cm2)
const double atm = 1.01325 * bar; // Standard atmosphere

const 关键字不仅仅用于声明常量变量。您还可以使用它来创建常量值,以及声明创建常量值的构造函数。任何变量都可以有一个常数值。

var foo = const [];
final bar = const [];
const baz = []; // Equivalent to `const []`

您可以从 const 声明的初始化表达式中省略 const,就像上面的 baz 一样。有关详情,请参阅DON’T use const redundantly

您可以更改非最终、非常量变量的值,即使它曾经具有 const 值:

foo = [1, 2, 3]; // Was const []

您无法更改 const 变量的值:

baz = [42]; // Error: Constant variables can't be assigned a value.

您可以定义使用 type checks and castsisas)、collection ifspread operators(... 和 ...{{ 1}}):

?

有关使用 const 创建常量值的详细信息,请参阅 ListsMapsClasses

答案 13 :(得分:0)

我可以用简洁的方式描述所有这些答案。

Final 变量无需初始化即可声明。但是在初始化或赋值之后我们就不能重新赋值了。

Const 变量在声明时必须用一个值初始化,显然与 Final 类似,我们不能重新分配它。

看截图。

<块引用>

注意RED 标记定义错误,BLUE 标记定义 - 声明但未使用。

enter image description here

答案 14 :(得分:-1)

带有 final 关键字的变量将在运行时初始化,并且只能分配一次。

带有 const 关键字的变量在编译时初始化,并在运行时已分配。

使用 final:如果你不知道它在编译时的值是什么。例如,当您需要从 API 获取数据时,就会在运行代码时发生这种情况。 使用 const:如果您确定在运行代码时不会更改某个值。例如,当您声明一个始终保持不变的句子时。