dart是强类型语言;js是弱类型语言。

  • 在 Dart 中一切变量皆是对象,每个对象都是类的实例。所有对象都继承自 Object 类。
  • 与 Java 语言相比,dart 语言包含的类似的基本数据类型只有 intdouble 两种。
  • intdoublenum类 的子类,也是对象,其默认值均为 null
  • null 是空对象。
  • 变量仅存储对象引用。

变量的声明

var

第一种:var 变量名 = 变量值

dart 是强类型语言,第一次声明赋值后,会自动判断数据类型。

  1. // 如果没有初始值,可以变成任意类型;
  2. var s1;
  3. s1 = 1;
  4. print(s1); //1
  5. s1 = true;
  6. print(s1); //true
  7. // 如果在声明时设置初始值,那么变量类型确定,切不能再次修改类型。
  8. var s2 = 1;
  9. s2 = 2;
  10. s2 = true; //报错
  11. var name = 'Bob';
  12. // 变量仅存储对象引用,这里的变量是 name 存储了一个 String 类型的对象引用。
  13. // “Bob” 是这个 String 类型对象的值。

上面代码中 name 变量的类型被推断为 String 。 但是也可以通过指定类型的方式,来改变变量类型。 如果对象不限定为单个类型,可以指定为 对象类型动态类型, 参考 设计指南

第二种(固定变量值):数据类型 变量名 = 变量值
  1. void main() {
  2. String str = 'age';
  3. print(str); // 'age'
  4. int num = 1;
  5. print(num); //1
  6. }

dynamic

动态任意类型,编译阶段不检查检查类型。在声明时设置初始值,变量类型可以再次修改。

类似于 Java 中的 Objectdynamic 对象可以用来指向任意类型变量,非 null 的 dynamic 变量会有具体的运行时类型。

  1. dynamic s1 = "age";
  2. print(s1.runtimeType); //String
  3. s1 = 18;
  4. print(s1.runtimeType); //int
  5. s1.run(); //未声明方法,编译时不报错,运行时会报错

image.png

Object

动态任意类型,编译阶段检查类型。在声明时设置初始值,变量类型可以再次修改。

  1. Object s1 = "age";
  2. print(s1.runtimeType); //String
  3. s1 = 18;
  4. print(s1.runtimeType); //int
  5. s1.run(); //未声明方法,编译时直接报错

image.png

类型推断

dart 语言是强类型语言,和js不一样,定义了后数据类型就不能再改变。
无法将一个已声明具体变量类型的变量赋值为另一个无继承关系的变量。

注意:int 不能再赋值成浮点数,但是浮点数可以赋值整数。 有关更多信息,请阅读 类型推断。

  1. // s1 默认类型推断为 int,如果再进行类型修改,就会报错。
  2. var s1 = 1;
  3. s1 = 2;
  4. // s1 = 'age'; //报错 Error: A value of type 'String' can't be assigned to a variable of type 'int'.
  5. // s3 = 2.2; //报错,虽然 int 和 double 都是 num类 的子类,但是仍不允许把 double类型的数据 赋值给 int变量。
  6. print(s1); //2
  7. // s1 默认类型推断为 double
  8. var s2 = 1.1;
  9. s2 = 2.2;
  10. s2 = 3; //int类型的数据 可以赋值给 double变量,但是会被转成double类型,所以输出3.0
  11. print(s2); //3.0
  12. // s3 默认类型推断为 String
  13. var s3 = 'age';
  14. s3 = 'book';
  15. // s3 = 1; //报错
  16. print(s3); //'book'

变量的默认值

  • 未初始化的变量 默认值是 null
  • 未赋值的变量 默认值是 null
  • 在 Dart 中一切都是对象,数字类型 也不例外。即便变量是数字类型,默认值也是 null

    1. void main() {
    2. // 未初始化的变量默认值是 null
    3. var s1;
    4. print(s1); //null
    5. // 未赋值的变量默认值是 null
    6. String s2;
    7. print(s2); //null
    8. // 即便变量是数字类型,默认值也是 null
    9. int num1;
    10. print(num1); //null
    11. double num2;
    12. print(num2); //null
    13. }

变量的命名规范

1、变量名称必须有数字、字母、下划线或者$组成
2、标识符不能数字开头
3、标识符不能用保留字和关键字
4、变量的名字是区分大小写的
5、标识符要有意义

runtimeType 获取一个对象的类型描述

  1. print('age'.runtimeType); //String
  2. print(true.runtimeType); //bool
  3. print((Symbol('a')).runtimeType); //Symbol
  4. // num
  5. print(1.runtimeType); //int
  6. print(1.1.runtimeType); //double
  7. // List
  8. print(([1, 2]).runtimeType); //List<int>
  9. print((['a', 'b']).runtimeType); //List<String>
  10. print(([1, 2, 'a']).runtimeType); //List<Object>
  11. print(([]).runtimeType); //List<dynamic>
  12. // Map
  13. // 注意:{} 默认为Map,因为作者在创建语言的时候,先有的Map
  14. print({}.runtimeType); //_InternalLinkedHashMap<dynamic, dynamic>
  15. print({'age': 18}.runtimeType); //_InternalLinkedHashMap<String, int>
  16. // Set
  17. print({1, 2}.runtimeType); //_CompactLinkedHashSet<int>

常量

如果你希望一个变量在赋值后其引用不能再改变,可以通过 finalconst 这两个关键字来实现。

  • const 变量代表的是编译时常量,在编译期,程序运行前就有确定值了,因此实例变量不能使用 const 修饰。
  • final 修饰的变量是运行时常量,可以在运行时再赋予变量值,因此实例变量能使用 final 修饰
  1. void main() {
  2. const a = 1; //const值一开始初始化的时候必须赋值
  3. const String name = 'lili';
  4. print(a); //1
  5. print(name); //'lili'
  6. final b = 2;
  7. final int age = 18;
  8. print(b); //2
  9. print(age); //18
  10. }

相似点

类型声明可以省略

  1. const int s1 = 1;
  2. const s2 = 1;
  3. final int s3 = 1;
  4. final s4 = 1;

初始化后不能再赋值

  1. const s1 = 1;
  2. s1 = 2; //Error: Can't assign to the const variable 's1'.
  3. final s2 = 1;
  4. s2 = 2; //Error

初始化未赋值

  1. const s1; //报错
  2. final s2; //报错
  3. // Error: The const variable 's1' must be initialized.
  4. // Try adding an initializer ('= expression') to the declaration.

不能和var同时使用

  1. const var a = 1;//报错
  2. final var a = 1;//报错
  3. // Error: Members can't be declared to be both 'var' and 'const'.
  4. // Try removing one of the keywords.

不同点:

类级别的常量,通常用 static const

const 只能用其它const常量的值;final用const、final都行

  1. const a = 100;
  2. const b = 20;
  3. // final b = 20; //如果const使用了其它final常量,就会报错
  4. const c = a * b;
  5. print(c); //2000
  6. const x = 100;
  7. final y = 20; //final既可以使用其它const常量、也可以使用其它final常量的值
  8. final z = x * y;
  9. print(z); //2000

const只能是编译时常量;final可以是运行时常量

即:final 可以让右边的先执行完,再把结果赋值给左边;const就不行,必须是一个确定的值。

  1. final nowTime = new DateTime.now();
  2. print(nowTime); //2020-10-28 01:44:30.530415
  3. const nowTime = new DateTime.now();
  4. //Error: New expression is not a constant expression.

const的不可变性是可传递的;final不是

  1. final s1 = [1, 2, 3];
  2. s1[1] = 11;
  3. print(s1); //[1, 11, 3]
  4. const s2 = [1, 2, 3];
  5. s2[1] = 11; //报错:nsupported operation: Cannot modify an unmodifiable list

内存中,final会重复创建;const会引用相同的值

  1. const s1 = [1, 2];
  2. const s2 = [1, 2];
  3. print(s1 == s2); //true
  4. print(identical(s1, s2)); //true
  5. final s3 = [1, 2];
  6. final s4 = [1, 2];
  7. print(s3 == s4); //false
  8. print(identical(s3, s4)); //false