(二)Dart变量、常量和数据类型

按照惯例,先来个 Hello World 😂

void main() {
  
  print('Hello World');
}

一、变量与常量

1.1.变量

  • 没有初始化的变量默认值为 null,基本数据类型未初始化也是null(Dart 中甚至连 数字、方法和 null 都是对象)。
  int a;
  double b;
  String s;
  Object c;
  dynamic d;
  var e;

  print(a); // null
  print(b); // null
  print(s); // null
  print(c); // null
  print(d); // null
  print(e); // null
  • 可选的类型:如果变量没有明确的类型,可以使用Objectdynamic关键字。
  dynamic a = 5;
  dynamic b = 5.6;
  dynamic c = 'sss';
  
  var d = 5;
  var e = 5.6;
  var f = 'sss';
  • 在声明变量的时候,可以选择加上具体类型,这样可以更加清晰的表达你的意图。 IDE 编译器等工具有可以使用类型来更好的帮助你, 可以提供代码补全、提前发现 bug 等功能。
  int a = 5;
  double b = 4.1;
  String s = 'sss';
  List list = [56,3,4,6,0];
  Map map = {
    'key1':'value1',
    'key2':'value2'
  };

注意:在 Dart 中有两种表示所有对象的类型:Object 和 dynamic。但是表达的意义不同:
Object 类型说明:可以接受任意对象,只需要这个对象定义了 Object 所定义的函数 即可。
dynamic 类型说明:没有一个类型可以表达你所期望的对象。 (有可能有类型可以表达,但是你不在乎。)

如下示例:

// 接受任意对象.
void log(Object object) {
  print(object.toString());
}

// 仅接受 bool 或者 String 类型, 它们不能在类型注解中表示。
bool convertToBool(arg) { // dynamic arg,默认 dynamic 类型,可省略
  if (arg is bool) return arg;
  if (arg is String) return arg == 'true';
  throw new ArgumentError('Cannot convert $arg to a bool.');
}

1.2.final and const

  • 如果以后不打算修改一个变量,可以使用 final 或者 const,被final 或者 const修饰的变量在第一次声明时必须初始化,否则编译器报错。
  //  报错:The final variable 's1' must be initialized.
  final String s1;
  //  报错:The const variable 's2' must be initialized.
  const String s2;
  • final 或者 const修饰的变量、对象实例一旦初始化,就不能再次赋值,否则编译器报错。
  final String s1 = 'ss';
  //  报错:s1,a final variable ,can only be set once.
  s1 = 'bb';
  
  const String s2 = 'ss';
  //  报错:Constant variables cant't be assigned a value.
  s2 = 'ff';
  • 实例变量可以被 final 修饰但是不能被 const 修饰,否则编译器报错。
class Person {
  
}

class Son {
  
  final Person p1 = Person();
  //  报错:Only static field can be declared as const.
  const Person p2 = Person();
}
  • final 或者 const 不能和 var 同时使用,否则编译器报错。
  //  报错:Members can't be declared to be both 'const' and 'var'
  const var String s1 = 'Tim';

  //  报错:Members can't be declared to be both 'final' and 'var'
  final var String s2 = 'Tim';
  • final或者const修饰的变量,变量类型可以省略,建议指定数据类型。
  const a = 'Tim';
  const b = 4;
  const c = 4.5;
  final d = 'Tim';
  final e = 4;
  final f = 4.5;
  • const 变量为编译时常量。 如果 const 变量在类中,请定义为 static const。 可以直接定义 const 和其值,也 可以定义一个const 变量使用其他 const 变量的值来初始化其值。
class Son {

  static const String name1 = 'Tom';
  // 报错: Only static fields can be declared as const
  const String name4 = 'Tom';

  void test() {
    
    const String name2 = 'Tom';
    const bar = 1000000;
    const atm = 1.01325 * bar;
    //  报错:Cant't have modifier 'static' here.
    static const String name3 = 'Tom';
  }

}
  • const 关键字不仅仅只用来定义常量。 有可以用来创建不变的值, 还能定义构造函数为 const 类型的,这种类型 的构造函数创建的对象是不可改变的。任何变量都可以有一个不变的值。 但是const常量必须用const类型的值初始化,否则编译器报错。
  void test() {

    var foo = const [];   // foo is currently an EIA.
    final bar = const []; // bar will always be an EIA.
    const baz = const []; // baz is a compile-time constant EIA.

    const bar1 = 1000000;
    final atm1 = 1.01325 * bar1;

    final bar2 = 1000000;
    // 报错:Constant variables must be initialized with a constant value.
    const atm2 = 1.01325 * bar2;
  }
  • 一个 const 变量是编译时常量。 (Const 变量同时也是 final 变量。) 顶级的 final 变量或者类中的 final 变量在 第一次使用的时候初始化。

二、num

Dart 支持两种类型的数字:

  • int整数值,其取值通常位于 -253 和 253 之间。
  • double 64-bit (双精度) 浮点数,符合 IEEE 754 标准。

intdouble 都是 num 的子类。 num 类型定义了基本的操作符,例如 +, -, /, 和*, 还定义了 abs()ceil()、和 floor() 等 函数。 (位操作符,例如>> 定义在 int 类中。) 如果num 或者其子类型不满足你的要求,请参考 dart:math 库,这些都是各种语言相同的套路,不多说。

  var x = 1;
  var hex = 0xDEADBEEF;
  var bigInt = 9223372036854775807;
  var y = 1.1;
  var exponents = 1.42e5;

  int x2 = 2;
  double x3 = 6;

  print('x = $x'); // x = 1
  print(hex); // 3735928559
  print(bigInt); // 9223372036854775807
  print(y); // 1.1
  print(exponents); // 142000.0

  print(x2); // 2
  print(x3); // 6.0

三、bool

  • Dart 是强 bool 类型检查,只有bool 类型的值是true 才被认为是true,否则false。这点和某些语言不一样, 像 1、 "aString"、 以及 someObject 等值都被认为是 false(应该是Dart version 2.0之前的版本)。

  • 在Dart version 2.0以后版本(本文Dart version 2.1.2),如果数据类型不是bool类型值却进行了条件判断,Dart Analysis则会报错。

  • boo类型的值是truefalse都是编译时常量。

  • assert 是Dart语言内置的断言函数,仅在检查模式下有效
    在开发过程中,除非条件为真,否则会引发异常。(断言失败则程序立刻终止)。

非bool值类型值条件判断,编译器报错

四、String

  • Dart 字符串是 UTF-16 编码的字符序列。 可以使用单引号或者双引号来创建字符串。
  var s1 = 'Single quotes work well for string literals.';
  var s2 = "Double quotes work just as well.";
  // 单引号中有单引号需要加转义字符
  var s3 = 'It\'s easy to escape the string delimiter.';
  /// 双引号中有单引号不需要加转义字符
  var s4 = "It's even easier to use the other delimiter.";
  // 单引号中使用双引号
  var s5 = '分为可"区分"情况分';
  • 使用三个单引号或者双引号也可以创建多行字符串对象:
  var s6 = '''
  You can create
  multi-line strings like this one.
  ''';
  var s7 = """This is also a
  multi-line string.""";
  • 可以在字符串中使用表达式,规则:${expression}。如果表达式是一个对象(在Dart中变量也是对象),可以省略 {}, Dart 会调用对象的 toString() 函数来获取一个字符串。若表达式不是对象表达式不可省略!
  var s8 = 'hello';
  var s9 = '$s8 world';
  print(s9); // hello world

  var s10 = '${s8.toUpperCase()} WORLD';
  print(s10); // HELLO WORLD

  // {} 不可省略
  var s11 = '$s8.toUpperCase() WORLD';
  print(s11); // hello.toUpperCase() WORLD
  • 一个带有r 前缀可以创建一个 “原始 raw” 字符串:
  var s12 = r"In a raw string, even \n isn't special.";
  print(s12); // In a raw string, even \n isn't special.
  • 字符串字面量是编译时常量, 带有字符串插值的字符串定义,若干插值表达式引用的为编译时常量则其结果也是编译时常量。
// These work in a const string.
    const aConstNum = 0;
    const aConstBool = true;
    const aConstString = 'a constant string';

    // These do NOT work in a const string.
    var aNum = 0;
    var aBool = true;
    var aString = 'a string';
    const aConstList = const [1, 2, 3];

    const validConstString1 = '$aConstNum $aConstBool $aConstString';
    print(validConstString1); // 0 true a constant string

    // 报错:Const variables must be initialized with a constant value.
    const validConstString2 = '$aNum $aBool $aString $aConstList';
    
    var validConstString3 = '$aNum $aBool $aString $aConstList';
    print(validConstString3);// 0 true a string [1, 2, 3]
  • 字符串的拼接
    String s1 = 'hello';
    String s2 = 'world';

    // 官方不推荐
    String s3 = s1 + s2;
    // 官方推荐
    String s4 = '$s1$s2';

    print(s3); // helloworld
    print(s4); // helloworld

五、List

  • array (或者有序集合)是所有编程语言中最常见的集合类型。 在 Dart 中数组就是 List 对象。所以 通常我们都称之为 lists。Dart list 字面量和 JavaScript 的数组字面量类似。

  • list里面的元素必须保持类型一致,不一致就会报错。

  • list的角标从0开始

  • list里面有多个相同的元素“X”, 调用list对象的remove()方法只会删除集合中第一个该元素。

  • 在java中必须遍历才能打印list,直接打印是地址值。Dart语言可以直接打印list包括list的元素。

  • list 字面量之前添加 const 关键字,可以 定义一个不变的 list 对象(编译时常量)。

//创建一个int类型的list
 List list = [10, 7, 23];
 // 输出[10, 7, 23]
 print(list);
 
 // 使用List的构造函数,也可以添加int参数,表示List固定长度,不能进行添加 删除操作
 var fruits = new List();
 
 // 添加元素
 fruits.add('apples');
 
 // 添加多个元素
 fruits.addAll(['oranges', 'bananas']);
 
 List subFruits = ['apples', 'oranges', 'banans'];
 // 添加多个元素
 fruits.addAll(subFruits);
 
 // 输出: [apples, oranges, bananas, apples, oranges, banans]
 print(fruits);
 
 /*
    获取List的长度,判断List是否为空时最好不要用lenth属性,
    用isEmpty或者isNotEmpty,可以提高性能
 */
 print(fruits.length);

 // 判断List是否为空
 bool isEmpty = fruits.isEmpty;
 bool isNotEmpty = fruits.isNotEmpty;

 // 获取第一个元素
 print(fruits.first);
 
 // 获取元素最后一个元素
 print(fruits.last);
 
 // 利用索引获取元素
 print(fruits[0]);
 
 // 查找某个元素的索引号
 print(fruits.indexOf('apples'));
 
 // 删除指定位置的元素,返回删除的元素
 print(fruits.removeAt(0));

 // 删除指定元素,成功返回true,失败返回false
 // 如果集合里面有多个“apples”, 只会删除集合中第一个该元素
 fruits.remove('apples');

 // 删除最后一个元素,返回删除的元素
 fruits.removeLast();

 // 删除指定范围(索引)元素,含头不含尾
 fruits.removeRange(start,end);

 // 删除指定条件的元素(这里是元素长度大于6)
 fruits.removeWhere((item) => item.length >6);

 // 删除所有的元素
 fruits.clear();

 /*
    在 `list` 字面量之前添加 `const` 关键字,
    可以 定义一个不变的 `list` 对象(编译时常量)
 */
 var constantList = const [1, 2, 3];
  • 排序。

排序一个 list 可以使用 sort() 函数。还可以提供一个用来排序 的比较方法。排序方法返回值 为:对于小的值 为 < 0;对于相同的值为 0 ;对于大的值为 > 0。 下面的示例使用由 Comparable 定义的 compareTo() 函数,该函数也被 String 实现了。

var fruits = ['bananas', 'apples', 'oranges'];

// Sort a list.
/**
   * Sorts this list according to the order specified by the [compare] function.
   *
   * The [compare] function must act as a [Comparator].
   *
   *     List<String> numbers = ['two', 'three', 'four'];
   *     // Sort from shortest to longest.
   *     numbers.sort((a, b) => a.length.compareTo(b.length));
   *     print(numbers);  // [two, four, three]
   *
   * The default List implementations use [Comparable.compare] if
   * [compare] is omitted.
   *
   *     List<int> nums = [13, 2, -11];
   *     nums.sort();
   *     print(nums);  // [-11, 2, 13]
   *
   * A [Comparator] may compare objects as equal (return zero), even if they
   * are distinct objects.
   * The sort function is not guaranteed to be stable, so distinct objects
   * that compare as equal may occur in any order in the result:
   *
   *     List<String> numbers = ['one', 'two', 'three', 'four'];
   *     numbers.sort((a, b) => a.length.compareTo(b.length));
   *     print(numbers);  // [one, two, four, three] OR [two, one, four, three]
   */
fruits.sort((a, b) => a.compareTo(b));
assert(fruits[0] == 'apples');

六、Set

Dart 中的 Set 是一个无序集合,里面不能保护重复的数据。 由于是无序的,所以无法通过索引来从 set 中获取数据:

var ingredients = new Set();
ingredients.addAll(['gold', 'titanium', 'xenon']);
assert(ingredients.length == 3);

// Adding a duplicate item has no effect.
ingredients.add('gold');
assert(ingredients.length == 3);

// Remove an item from a set.
ingredients.remove('gold');
assert(ingredients.length == 2);
  • 使用 contains()containsAll() 来判断 set 中是否包含 一个或者多个对象:
var ingredients = new Set();
ingredients.addAll(['gold', 'titanium', 'xenon']);

// Check whether an item is in the set.
assert(ingredients.contains('titanium'));

// Check whether all the items are in the set.
assert(ingredients.containsAll(['titanium', 'xenon']));
  • 交集是两个 set 中都有的数据的子集:
var ingredients = new Set();
ingredients.addAll(['gold', 'titanium', 'xenon']);

// Create the intersection of two sets.
var nobleGases = new Set.from(['xenon', 'argon']);
// 拿到交集的值(Set类型)
var intersection = ingredients.intersection(nobleGases);
assert(intersection.length == 1);
assert(intersection.contains('xenon'));

七、Map

  • 通常来说,Map 是一个键值对相关的对象。 键和值可以是任何类型的对象。

  • Map中的键是唯一的,相同Key的值会覆盖之前的数据。

  • 值可以为空字符串或者null

  • 所查找的键不存在,则返回 null

  • 使用 .length 来获取 Map 中键值对的数目。

  • 可使用const 可以创建一个编译时常量的 Map

    // 声明并赋值
    var gifts = {
      // Keys      Values
      'first': 'partridge',
      'second': 'turtledoves',
      'fifth': 'golden rings'
    };

    var nobleGases = {
      // Keys  Values
      2: 'helium',
      10: 'neon',
      18: 'argon',
    };

    // 先声明,后赋值
    Map map1 = new Map();
    map1['first'] = 'value1';
    map1['second'] = 'value2';
    map1['third'] = 'value3';

    var map2 = new Map();
    map2[2] = 'helium';
    map2[10] = 'neon';
    map2[18] = 'argon';

    // 指定键值对的参数类型
    var aMap = new Map<int, String>();

    // Map的赋值,中括号中是Key,这里可不是数组
    aMap[1] = '小米';

    /*
      Map中的键是唯一的,相同Key的值会覆盖之前的数据
     */
    aMap[1] = 'alibaba';

    // map里面的value可以相同
    aMap[2] = 'alibaba';

    // map里面value可以为空字符串
    aMap[3] = '';

    // map里面的value可以为null
    aMap[4] = null;
    print(aMap);

    // 检索Map是否含有某Key
    assert(aMap.containsKey(1));
    
    /*
    获取键值对个数,判断Map是否为空时最好不要用lenth属性,
    用isEmpty或者isNotEmpty,可以提高性能
    */
    print(aMap.length);

    // 判断List是否为空
    bool isEmpty = aMap.isEmpty;
    bool isNotEmpty = aMap.isNotEmpty;

    //删除某个键值对
    aMap.remove(1);
    print(aMap);

    // 可使用const 可以创建一个编译时常量的 Map。
    final constantMap = const {
      2: 'helium',
      10: 'neon',
      18: 'argon',
    };

八、Runes

在 Dart 中,runes 代表字符串的 UTF-32 code points。

Unicode 为每一个字符、标点符号、表情符号等都定义了 一个唯一的数值。 由于 Dart 字符串是 UTF-16 code units 字符序列, 所以在字符串中表达 32-bit Unicode 值就需要 新的语法了。

通常使用 \uXXXX 的方式来表示 Unicode code point, 这里的 XXXX 是4个 16 进制的数。 例如,心形符号 (♥) 是 \u2665。 对于非 4 个数值的情况, 把编码值放到大括号中即可。 例如,笑脸 emoji (😆) 是 \u{1f600}

String 类 有一些属性可以提取 rune 信息。 codeUnitAtcodeUnit 属性返回 16-bit code units。 使用 runes 属性来获取字符串的runes 信息。

    var clapping = '\u{1f44f}';
    print(clapping); // 👏
    print(clapping.codeUnits); // [55357, 56399]
    print(clapping.runes.toList()); // [128079]

    Runes input = new Runes(
        '\u2665  \u{1f605}  \u{1f60e}  \u{1f47b}  \u{1f596}  \u{1f44d}');
    print(new String.fromCharCodes(input)); // ♥  😅  😎  👻  🖖  👍

九、Symbol

Symbol字面量定义是编译时常量,一个 Symbol object 代表 Dart 程序中声明的操作符或者标识符。 你也许从来不会用到 Symbol,但是该功能对于通过名字来引用标识符的情况 是非常有价值的,特别是混淆后的代码, 标识符的名字被混淆了,但是 Symbol 的名字不会改变。关于 symbols 的详情,请参考 dart:mirrors - reflection

使用 Symbol 字面量来获取标识符的 symbol 对象,也就是在标识符 前面添加一个 # 符号:

#radix
#bar
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,636评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,890评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,680评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,766评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,665评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,045评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,515评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,182评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,334评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,274评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,319评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,002评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,599评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,675评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,917评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,309评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,885评论 2 341

推荐阅读更多精彩内容