在Dart语言中,有两个声明常量的修饰符即final和const,它们都能表示常量,一旦赋值就不能再重新赋值,那么这两种常量有什么区别呢?
要弄懂它们的区别,先要理解什么是编译时常量,什么是运行时常量。
编译时常量,就是它的值在编译时就能确定的常量,不是等到运行时才确定。
运行时常量,就是在它的值在程序运行时才能确定。
const是编译时常量,final就是运行时常量。
在Java语言中没有这两种常量的区分,只有final类型修饰的常量。但是Java中的final既可以表示编译时常量也可以表示运行时常量。具体看它的初始值是不是8种基本数据类型或String类型的常量,是则是编译时常量,否则是运行时常量。
编译时常量有一个风险,就是当它的初始值引用了另外一个类的常量,当另外一个被引用的类在运行时替换了,那么引用它的那个编译时常量并不会受到影响。比如你的应用引用了一个jar包,这个jar包运行时可以动态替换,当你修改了jar中的常量,那么实际引用它的另外一个常量并不会被修改。
Java中的编译时常量示例:
class FinalDemo{
public static final int test1=100;
public static final long test2=1000l;
public static final float test3=100.00f;
public static final double test4=100.00d;
public static final boolean test5=true;
public static final String test6="hello";
public static final char test7='a';
public static final short test8=100;
}
Java中的运行时常量示例:
class FinalDemo2{
public static final Integer test1=new Integer(100);
public static final long test2=System.currentTimeMillis();
public static final float test3=new Float(100.00f);
public static final double test4=new Double(100.00d);
public static final boolean test5=new Boolean("true");
public static final String test6=new String("hello");
public static final Character test7=new Character('a');
}
对于Java中的这种常量隐藏的风险,程序员很可能不小心就踩雷。
因此,Dart语言对这两个常量进行了区分:使用const表示的是编译时常量,final表示运行时常量。
那么在使用时有什么区别呢?
const修饰的常量必须在声明时初始化,并且是可以确定的值,不是需要经过计算的值。
final修饰的常量必须在声明进初始化或者在构造函数中初始化,它的值可以动态计算。
共同点是两者赋值后就不能再修改(不能重新赋值,对于引用类型可以修改属性)。
看一个Dart的常量实例:
main() {
const test1="hello";//正确,编译期常量
final test2="hello";//正确,运行时常量
const test3=DateTime.now();//编译报错,值不是编译期常量
final test4=DateTime.now();//正确,运行时常量
const test5=new List();//编译报错,值不是编译期常量
final test6=new List();//正确,运行时常量
}