在Dart中,final和const都用于声明常量,它们的区别是什么?

207 阅读3分钟

在Dart中,finalconst都用于声明常量,但它们有一些重要的区别。让我们来详细了解一下这两个关键字的区别:

1.final修饰的特点

  • final用于声明一个在运行时确定值的常量。这意味着你可以在运行时为final变量分配一个值,但一旦赋值后,它的值将保持不变。
    • 示例:
main(List<String> args){
  final int age = 30;  // 在运行时确定值为30
  // age = 31;  // 这里会导致错误,一旦赋值后不可更改
  print("Age: $age");
}
  • final变量可以在声明时或构造函数中初始化,但一旦初始化后就不能再次赋值。

(1).声明变量后不能再次赋值示例:

main(List<String> args){
  final String name = "John";  // 初始化后不可再次赋值
  // name = "Alice";  // 这里会导致错误,初始化后不可再次赋值
  print("Name: $name");
}

(2).构造函数中也是同样示例:

class Person {
  final String name;
  final int age;

  Person(this.name, this.age);  // 构造函数,使用final声明

  void displayInfo() {
    print("Name: $name, Age: $age");
  }
}

main(List<String> args){ 
  final Person person = Person("John", 30);  // 创建Person对象

  person.displayInfo();  // 调用对象的方法

  // 下面的代码会导致错误,因为name和age已经在构造函数中被赋值,不能再修改
  // person.name = "Alice";
  // person.age = 25;
}

在上边示例中,Person类有两个final成员变量:nameage。构造函数中使用this.namethis.age来初始化这些成员变量。一旦在构造函数中初始化,这些成员变量的值就不能在对象创建后被修改。

  • final变量的值在运行时确定,可以根据条件来设置,可以通过计算等方式确定。
main(List<String> args){ 
  final bool isAdult = true;
  final int age = isAdult ? 25 : 15;  // 根据条件运行时确定值
  print("Is Adult? $isAdult");
  print("Age: $age");
}
  • final变量的值可以是任何数据类型,包括基本类型(如数字、字符串)和对象类型。

示例:

main(List<String> args) {
  final dynamic value = "Hello";  // final变量可以是任何数据类型
  print("Value: $value");
}

2.const的特点

  • const用于声明一个在编译时确定值的常量。这意味着const变量的值必须在编译时就能够确定,而不能通过运行时计算或条件来确定。
  • const变量必须在声明时初始化,不能在构造函数中初始化,也不能通过任何运行时操作改变其值。
  • const变量的值只能是编译时已知的常量,例如文字字符串、数值、布尔值等,或者是由其他const变量组成的表达式。
  • const变量的值也可以是对象类型,但这些对象必须是在编译时可知的常量对象。

示例:

dartCopy code
const int age = 30;
const String name = "John";
const List<int> numbers = [1, 2, 3]; // 这里会报错,因为List不是常量对象

3.两者在方法调用上区别

main(List<String> args){
  //const test111 = getTest(); // 错误的做法, 因为要执行函数才能获取到值
  final test222 = getTest(); // 正确的做法
}

String getTest() {
  return '1111111111';
}

上述示例分析:

const修饰会报错,因为要执行函数才能获取到值。

final修饰不会报错。

4.两者修饰对象的区别


main(List<String> args){

  
  //final修饰的对象不能算是同一个对象
  // final obj1 = Animal('obj');
  // final obj2 = Animal('obj');
  // print(identical(obj1, obj2)); //false

  //final修饰的对象是同一个对象
  const obj1 = Animal('obj');
  const obj2 = Animal('obj');
  print(identical(obj1, obj2)); //true
}

class Animal {
  final String name;
  const Animal(this.name);
}

上述示例分析:

使用final修饰的对象,即使它们的属性值相同,也被视为不同的对象。 使用const修饰的对象,如果它们的属性值相同且在编译时可以确定,会被视为同一个常量对象。

总结:

  • 使用final当你需要一个在运行时确定值的常量,且你需要在运行时为它分配一个值。
  • 使用const当你需要一个在编译时确定值的常量,且其值必须在编译时就能够确定,可以通过字面值或其他const变量组成的表达式来初始化。

需要注意的是,const的限制更严格,因为它要求常量在编译时就能够确定,这可能会导致一些使用上的限制。在选择使用final还是const时,你需要根据具体情况和需求来做出决策。