dart是强类型语言;js是弱类型语言。
- 在 Dart 中一切变量皆是对象,每个对象都是类的实例。所有对象都继承自 Object 类。
- 与 Java 语言相比,dart 语言包含的类似的基本数据类型只有
int和double两种。 int、double是num类 的子类,也是对象,其默认值均为null。null是空对象。- 变量仅存储对象引用。
变量的声明
var
第一种:var 变量名 = 变量值
dart 是强类型语言,第一次声明赋值后,会自动判断数据类型。
// 如果没有初始值,可以变成任意类型;var s1;s1 = 1;print(s1); //1s1 = true;print(s1); //true// 如果在声明时设置初始值,那么变量类型确定,切不能再次修改类型。var s2 = 1;s2 = 2;s2 = true; //报错var name = 'Bob';// 变量仅存储对象引用,这里的变量是 name 存储了一个 String 类型的对象引用。// “Bob” 是这个 String 类型对象的值。
上面代码中
name变量的类型被推断为 String 。 但是也可以通过指定类型的方式,来改变变量类型。 如果对象不限定为单个类型,可以指定为对象类型或动态类型, 参考 设计指南。
第二种(固定变量值):数据类型 变量名 = 变量值
void main() {String str = 'age';print(str); // 'age'int num = 1;print(num); //1}
dynamic
动态任意类型,编译阶段不检查检查类型。在声明时设置初始值,变量类型可以再次修改。
类似于 Java 中的 Object,dynamic 对象可以用来指向任意类型变量,非 null 的 dynamic 变量会有具体的运行时类型。
dynamic s1 = "age";print(s1.runtimeType); //Strings1 = 18;print(s1.runtimeType); //ints1.run(); //未声明方法,编译时不报错,运行时会报错

Object
动态任意类型,编译阶段检查类型。在声明时设置初始值,变量类型可以再次修改。
Object s1 = "age";print(s1.runtimeType); //Strings1 = 18;print(s1.runtimeType); //ints1.run(); //未声明方法,编译时直接报错

类型推断
dart 语言是强类型语言,和js不一样,定义了后数据类型就不能再改变。
无法将一个已声明具体变量类型的变量赋值为另一个无继承关系的变量。
注意:int 不能再赋值成浮点数,但是浮点数可以赋值整数。 有关更多信息,请阅读 类型推断。
// s1 默认类型推断为 int,如果再进行类型修改,就会报错。var s1 = 1;s1 = 2;// s1 = 'age'; //报错 Error: A value of type 'String' can't be assigned to a variable of type 'int'.// s3 = 2.2; //报错,虽然 int 和 double 都是 num类 的子类,但是仍不允许把 double类型的数据 赋值给 int变量。print(s1); //2// s1 默认类型推断为 doublevar s2 = 1.1;s2 = 2.2;s2 = 3; //int类型的数据 可以赋值给 double变量,但是会被转成double类型,所以输出3.0print(s2); //3.0// s3 默认类型推断为 Stringvar s3 = 'age';s3 = 'book';// s3 = 1; //报错print(s3); //'book'
变量的默认值
- 未初始化的变量 默认值是
null - 未赋值的变量 默认值是
null 在 Dart 中一切都是对象,数字类型 也不例外。即便变量是数字类型,默认值也是
nullvoid main() {// 未初始化的变量默认值是 nullvar s1;print(s1); //null// 未赋值的变量默认值是 nullString s2;print(s2); //null// 即便变量是数字类型,默认值也是 nullint num1;print(num1); //nulldouble num2;print(num2); //null}
变量的命名规范
1、变量名称必须有数字、字母、下划线或者$组成
2、标识符不能数字开头
3、标识符不能用保留字和关键字
4、变量的名字是区分大小写的
5、标识符要有意义
runtimeType 获取一个对象的类型描述
print('age'.runtimeType); //Stringprint(true.runtimeType); //boolprint((Symbol('a')).runtimeType); //Symbol// numprint(1.runtimeType); //intprint(1.1.runtimeType); //double// Listprint(([1, 2]).runtimeType); //List<int>print((['a', 'b']).runtimeType); //List<String>print(([1, 2, 'a']).runtimeType); //List<Object>print(([]).runtimeType); //List<dynamic>// Map// 注意:{} 默认为Map,因为作者在创建语言的时候,先有的Mapprint({}.runtimeType); //_InternalLinkedHashMap<dynamic, dynamic>print({'age': 18}.runtimeType); //_InternalLinkedHashMap<String, int>// Setprint({1, 2}.runtimeType); //_CompactLinkedHashSet<int>
常量
如果你希望一个变量在赋值后其引用不能再改变,可以通过 final 或 const 这两个关键字来实现。
const变量代表的是编译时常量,在编译期,程序运行前就有确定值了,因此实例变量不能使用 const 修饰。final修饰的变量是运行时常量,可以在运行时再赋予变量值,因此实例变量能使用 final 修饰
void main() {const a = 1; //const值一开始初始化的时候必须赋值const String name = 'lili';print(a); //1print(name); //'lili'final b = 2;final int age = 18;print(b); //2print(age); //18}
相似点
类型声明可以省略
const int s1 = 1;const s2 = 1;final int s3 = 1;final s4 = 1;
初始化后不能再赋值
const s1 = 1;s1 = 2; //Error: Can't assign to the const variable 's1'.final s2 = 1;s2 = 2; //Error
初始化未赋值
const s1; //报错final s2; //报错// Error: The const variable 's1' must be initialized.// Try adding an initializer ('= expression') to the declaration.
不能和var同时使用
const var a = 1;//报错final var a = 1;//报错// Error: Members can't be declared to be both 'var' and 'const'.// Try removing one of the keywords.
不同点:
类级别的常量,通常用 static const
const 只能用其它const常量的值;final用const、final都行
const a = 100;const b = 20;// final b = 20; //如果const使用了其它final常量,就会报错const c = a * b;print(c); //2000const x = 100;final y = 20; //final既可以使用其它const常量、也可以使用其它final常量的值final z = x * y;print(z); //2000
const只能是编译时常量;final可以是运行时常量
即:final 可以让右边的先执行完,再把结果赋值给左边;const就不行,必须是一个确定的值。
final nowTime = new DateTime.now();print(nowTime); //2020-10-28 01:44:30.530415const nowTime = new DateTime.now();//Error: New expression is not a constant expression.
const的不可变性是可传递的;final不是
final s1 = [1, 2, 3];s1[1] = 11;print(s1); //[1, 11, 3]const s2 = [1, 2, 3];s2[1] = 11; //报错:nsupported operation: Cannot modify an unmodifiable list
内存中,final会重复创建;const会引用相同的值
const s1 = [1, 2];const s2 = [1, 2];print(s1 == s2); //trueprint(identical(s1, s2)); //truefinal s3 = [1, 2];final s4 = [1, 2];print(s3 == s4); //falseprint(identical(s3, s4)); //false
