Dart 中的 const 关键字
2023-05-29 本文已影响0人
teletian
const 修饰内置数据类型
const 修饰内置数据类型,那么之后就不允许修改了,否则编译阶段会报错。
void main() {
const int a = 1;
// a = 2;
const double d = 1.0;
// d = 2.0;
const String str = "hello";
// str = "world";
const List list = [1, 2, 3];
// list = [4, 5, 6];
}
const 修饰自定义数据类型
如果要用 const 修饰自定义数据类型,那么它的构造方法也必须加 const,否则编译阶段会报错。
void main() {
// 此处编译报错:Const variables must be initialized with a constant value.
const Person p = Person("Jack", 11);
}
class Person {
String name;
int age;
Person(this.name, this.age);
}
构造方法加上 const 之后,编译器提示成员变量必须是 final 的。
void main() {
const Person p = Person("Jack", 11);
}
class Person {
String name;
int age;
// 此处编译报错:Can't define a const constructor for a class with non-final fields.
const Person(this.name, this.age);
}
继续给成员变量加 final 关键字,发现没有编译错误了。
void main() {
const Person p = Person("Jack", 11);
// p = Person("Rose", 12) // 不可以修改
}
class Person {
final String name;
final int age;
const Person(this.name, this.age);
}
注意:const 要加到前面才可以将变量的值设置为不可以被修改,如果 const 加到后面,变量的值还是可以被修改的。(那么,const 加到后面有什么意义呢?可以节省内存空间,下文有具体介绍,这里就不解释了)
void main() {
const Person p = Person("Jack", 11);
// p = Person("Rose", 12) // 不可以修改
Person p2 = const Person("Jack", 11);
p2 = const Person("Rose", 12); // 仍然可以修改
}
class Person {
final String name;
final int age;
const Person(this.name, this.age);
}
类中定义 const 的成员
类中定义 const 的成员,必须要加 static 关键字,这是固定的定义常量的写法。
class Person {
// static const 定义常量
static const String TAG = "MyTag";
final String name;
final int age;
const Person(this.name, this.age);
}
const 节省内存空间
来看看下面这个例子:
void main() {
for (var i = 0; i < 10; i++) {
Person p = const Person("Jack", 11);
print(p.hashCode);
}
}
class Person {
static const String TAG = "MyTag";
final String name;
final int age;
const Person(this.name, this.age);
}
for 循环中创建了 10 个 Person 对象,打印出来的 hash code 却是一模一样,这就说明了 10 次用的同一个对象,这样的好处就是节省内存空间。
这个在 flutter 中也很常用,对于一些不需要修改的控件,定义成 const,不管调用多少次,都是同一份内存空间:
const Text("Hello World!")
const 是编译期常量
const 是编译器常量,不能在其中使用只能在运行期间才能确定的变量。以下代码编译出错:
int count = 0;
const Text("次数:$count");
const 层级
如果上层是 const 的,下面的层级必须都是 const 的
const Padding(
padding: const EdgeInsets.all(10),
child: const Text("Hello World"),
);
子层级的 const 可以省略
const Padding(
padding: EdgeInsets.all(10),
child: Text("Hello World"),
);
如果外层加了 const,但是子层级中有不能修饰为 const 的控件,编译会报错
const 和 final 的区别
final 修饰的变量在第一次使用时被初始化,之后不允许修改。
const 修饰的变量是一个编译时常量,编译后会发现在用到常量的地方,直接用常量值替换了。