Built-in types(内置的类型)
Dart
内置支持下面这些类型:
numbers
strings
booleans
-
lists
(也被称之为arrays
) maps
-
runes
(用于在字符串中表示Unicode
字符) symbols
你可以直接使用字面量来初始化上面的这些类型。 例如 'this is a string'
是一个字符串字面量, true
是一个布尔值字面量。
由于Dart
中每个变量引用的都是一个对象 – 一个类的实例, 你通常使用构造函数来初始化变量。 一些内置的类型具有自己的构造函数。例如, 可以使用 Map()
构造函数来创建一个map
, 就像这样 new Map()
。
数值(Numbers)
Dart 支持两种类型的数字:
int
整数值,不超过64位,取决于使用平台。在Dart VM中其取值通常位于 -263 和 263 - 1 之间。当Dart
被编译为JavaScript
使用JavaScript numbers, 时,其取值通常位于 -253 和 253 - 1之间。
64-bit (双精度) 浮点数,符合 IEEE 754 标准。
int
和 double
都是 num
的子类。 num
类型定义了基本的操作符,例如 +, -, /, 和 *, 还定义了 abs()
、ceil()
、和 floor()
等 函数。 (位操作符,例如 >> 定义在 int
类中。) 如果 num 或者其子类型不满足你的要求,请参考 dart:math 库。
整数是不带小数点的数字。下面是一些定义整数字面量值的方式:
var x = 1;
var hex = 0xDEADBEEF;
如果一个数带小数点,则其为double
, 下面是定义double
的一些方式:
var y = 1.1;
var exponents = 1.42e5;
在Dart
2.1,当需要的时候,整形数值将自动转换为double类型
double z = 1; // Equivalent to double z = 1.0.
下面是字符串和数字之间转换的方式:
// String -> int
var one = int.parse('1');
assert(one == 1);
// String -> double
var onePointOne = double.parse('1.1');
assert(onePointOne == 1.1);
// int -> String
String oneAsString = 1.toString();
assert(oneAsString == '1');
// double -> String
String piAsString = 3.14159.toStringAsFixed(2);
assert(piAsString == '3.14');
整数类型支持传统的位移操作符,(<<, >>), AND (&), 和 OR (|) 。例如:
assert((3 << 1) == 6); // 0011 << 1 == 0110
assert((3 >> 1) == 1); // 0011 >> 1 == 0001
assert((3 | 4) == 7); // 0011 | 0100 == 0111
数字字面量为编译时常量。 很多算术表达式只要其操作数是常量,则表达式结果也是编译时常量。
const msPerSecond = 1000;
const secondsUntilRetry = 5;
const msUntilRetry = secondsUntilRetry * msPerSecond;
字符串(Strings)
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.";
可以在字符串中使用表达式,用法是这样的: ${expression}
。如果表达式是一个标识符,可以省略 {}。 如果表达式的结果为一个对象,则Dart
会调用对象的 toString()
函数来获取一个字符串。
var s = 'string interpolation';
assert('Dart has $s, which is very handy.' ==
'Dart has string interpolation, ' +
'which is very handy.');
assert('That deserves all caps. ' +
'${s.toUpperCase()} is very handy!' ==
'That deserves all caps. ' +
'STRING INTERPOLATION is very handy!');
注意: == 操作符判断两个对象的内容是否一样。 如果两个字符串包含一样的字符编码序列, 则他们是相等的。
可以使用 + 操作符来把多个字符串链接为一个,也可以把多个 字符串放到一起来实现同样的功能:
var s1 = 'String '
'concatenation'
" works even over line breaks.";
assert(s1 ==
'String concatenation works even over '
'line breaks.');
var s2 = 'The + operator ' + 'works, as well.';
assert(s2 == 'The + operator works, as well.');
另外一种方法是使用三个单引号或者双引号也可以创建多行字符串对象:
var s1 = '''
You can create
multi-line strings like this one.
''';
var s2 = """This is also a
multi-line string.""";
通过提供一个 r 前缀可以创建一个 “原始 raw” 字符串:
var s = r'In a raw string, not even \n gets special treatment.';
参考 Runes 来了解如何在字符串 中表达 Unicode 字符。
字符串字面量是编译时常量, 只要任意字符串插值表达式是常量,那么其值为null
或numeric
或string
, 或boolean
.
// 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 = [1, 2, 3];
const validConstString = '$aConstNum $aConstBool $aConstString';
// const invalidConstString = '$aNum $aBool $aString $aConstList';
字符串是不可变的,虽然我们不能改变字符串,但是仍然可以对字符串进行操作并赋值给新的字符串
var string = 'Dart is fun';
var newString = string.substring(0,4); // Dart
使用isEmpty
判断字符串是否为空
var string = 'Dart is fun';
print(string.isEmpty); // false
使用length
获取字符串的长度
var string = 'Dart is fun';
print(string.length); // 11
将字符串全部转换为大写或小写
var string = 'Dart is fun';
var lower = string.toLowerCase(); // dart is fun
var up = string.toUpperCase(); // DART IS FUN
可以在字符串内查找特定字符的位置,还可以 判断字符串是否以特定字符串开始和结尾。 例如:
// Check whether a string contains another string.
assert('Never odd or even'.contains('odd'));
// Does a string start with another string?
assert('Never odd or even'.startsWith('Never'));
// Does a string end with another string?
assert('Never odd or even'.endsWith('even'));
// Find the location of a string inside a string.
assert('Never odd or even'.indexOf('odd') == 6);
使用字符串的更多信息请参考:Strings and regular expressions和API
布尔值(Booleans)
为了代表布尔值,Dart
有一个名字为bool
的类型。 只有两个对象是布尔类型的:true
和 false
所创建的对象, 这两个对象也都是编译时常量。
Dart
类型安全,意味着你不能编写if (nonbooleanValue)
和assert (nonbooleanValue)
这样的代码。相反,应该显示的确认值
// Check for an empty string.
var fullName = '';
assert(fullName.isEmpty);
// Check for zero.
var hitPoints = 0;
assert(hitPoints <= 0);
// Check for null.
var unicorn;
assert(unicorn == null);
// Check for NaN.
var iMeantToDoThis = 0 / 0;
assert(iMeantToDoThis.isNaN);
列表(Lists)
也许 array (或者有序集合)是所有编程语言中最常见的集合类型。 在 Dart
中数组就是 List 对象。所以通常我们都称之为 lists。
Dart list
字面量和 JavaScript
的数组字面量类似。下面是一个Dart list
的示例:
var list = [1, 2, 3];
注意:上面list
,Dart
将推测其类型为List<int>
,如果添加非int类型值将报错
Lists
的下标索引从 0 开始,第一个元素的索引是 0,list.length - 1
是最后一个元素的索引。 访问list
的长度和元素与JavaScript
中的用法一样
var list = [1, 2, 3];
assert(list.length == 3);
assert(list[1] == 2);
list[1] = 1;
assert(list[1] == 1);
在 list
字面量之前添加const
关键字,可以 定义一个不变的list
对象(编译时常量):
var constantList = const [1, 2, 3];
// constantList[1] = 1; // Uncommenting this causes an error.
使用List
构造函数来创建List
对象。 List
类来定义了一些函数可以添加或者删除里面的数据。
// Use a List constructor.
var vegetables = List();
// Or simply use a list literal.
var fruits = ['apples', 'oranges'];
// Add to a list.
fruits.add('kiwis'); // [apples, oranges, kiwis]
// Add multiple items to a list.
fruits.addAll(['grapes', 'bananas']); // [apples, oranges, kiwis, grapes, bananas]
// Get the list length.
assert(fruits.length == 5);
// Remove a single item.
var appleIndex = fruits.indexOf('apples');
fruits.removeAt(appleIndex); // [oranges, kiwis, grapes, bananas]
assert(fruits.length == 4);
// Remove all elements from a list.
fruits.clear(); // []
assert(fruits.length == 0);
使用 indexOf()
来查找 list
中对象的索引:
var fruits = ['apples', 'oranges'];
// Access a list item by index.
assert(fruits[0] == 'apples');
// Find an item in a list.
assert(fruits.indexOf('apples') == 0);
List
是泛型类型,所以可以指定 里面所保存的数据类型:
// This list should contain only strings.
var fruits = List<String>();
fruits.add('apples');
var fruit = fruits[0]; // apples
assert(fruit is String); // true
List
类型有很多函数可以操作 list
。 更多信息参考 Generics and Collections和List API reference
集合(Sets)
Set
是Dart
中的拥有唯一item
的无序集合。Dart
支持对Set
直接使用字面量操作
简单的字面量集合
var halogens = {'fluorine', 'chlorine', 'bromine', 'iodine', 'astatine'};
创建空集合
var names = <String>{};
// Set<String> names = {}; // This works, too.
// var names = {}; // Creates a map, not a set.
为集合添加item,使用add()
和addAll()
方法
var elements = <String>{};
elements.add('fluorine');
elements.addAll(halogens);
使用.length
获取集合的items
个数
var elements = <String>{};
elements.add('fluorine');
elements.addAll(halogens);
assert(elements.length == 5);
为了创建一个编译时常量集合,使用const
final constantSet = const {
'fluorine',
'chlorine',
'bromine',
'iodine',
'astatine',
};
// constantSet.add('helium'); // Uncommenting this causes an error.
Dart
中的 Set
是一个无序集合,里面不能包含重复的数据。 由于是无序的,所以无法通过索引来从 set
中获取数据:
var ingredients = Set();
ingredients.addAll(['gold', 'titanium', 'xenon']);
assert(ingredients.length == 3);
// Adding a duplicate item has no effect.
ingredients.add('gold'); // {gold, titanium, xenon}
assert(ingredients.length == 3);
// Remove an item from a set.
ingredients.remove('gold'); // {titanium, xenon}
assert(ingredients.length == 2);
使用contains()
和 containsAll()
来判断 set
中是否包含 一个或者多个对象:
var ingredients = 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']));
更多信息可以看Generics 和 Sets以及Set API reference
Maps
通常来说,Map
通常也被称之为 字典或者hash
,是一个键值对相关的对象。 键和值可以是任何类型的对象。每个 键 只出现一次, 而一个值则可以出现多次。Dart
通过 map
字面量 和 Map 类型支持 map
。
下面是一些创建简单 map
的示例:
var gifts = {
// Key: Value
'first': 'partridge',
'second': 'turtledoves',
'fifth': 'golden rings'
};
// 推测为Map<String, String>
var nobleGases = {
2: 'helium',
10: 'neon',
18: 'argon',
};
// Map<int, String>
使用 Map
构造函数也可以实现同样的功能:
var gifts = Map(); // 也可以使用new Map(),new关键词是可选的
gifts['first'] = 'partridge';
gifts['second'] = 'turtledoves';
gifts['fifth'] = 'golden rings';
var nobleGases = Map();
nobleGases[2] = 'helium';
nobleGases[10] = 'neon';
nobleGases[18] = 'argon';
往 map
中添加新的键值对和在JavaScript
中的用法一样:
var gifts = {'first': 'partridge'};
gifts['fourth'] = 'calling birds'; // Add a key-value pair
获取 map
中的对象也和 JavaScript
的用法一样:
var gifts = {'first': 'partridge'};
assert(gifts['first'] == 'partridge');
如果所查找的键不存在,则返回 null
:
var gifts = {'first': 'partridge'};
assert(gifts['fifth'] == null);
使用 .length
来获取 map
中键值对的数目:
var gifts = {'first': 'partridge'};
gifts['fourth'] = 'calling birds';
assert(gifts.length == 2);
同样使用 const
可以创建一个 编译时常量的 map
:
final constantMap = const {
2: 'helium',
10: 'neon',
18: 'argon',
};
// constantMap[2] = 'Helium'; // Uncommenting this causes an error.
使用 remove()
函数来从 map
中删除 key
和 value
。
var nobleGases = {54: 'xenon'};
// Retrieve a value with a key.
assert(nobleGases[54] == 'xenon');
// Check whether a map contains a key.
assert(nobleGases.containsKey(54));
// Remove a key and its value.
nobleGases.remove(54);
assert(!nobleGases.containsKey(54));
还可以获取map
的所有 key
和 value
:
var hawaiianBeaches = {
'Oahu': ['Waikiki', 'Kailua', 'Waimanalo'],
'Big Island': ['Wailea Bay', 'Pololu Beach'],
'Kauai': ['Hanalei', 'Poipu']
};
// Get all the keys as an unordered collection
// (an Iterable).
var keys = hawaiianBeaches.keys;
assert(keys.length == 3);
assert(Set.from(keys).contains('Oahu'));
// Get all the values as an unordered collection
// (an Iterable of Lists).
var values = hawaiianBeaches.values;
assert(values.length == 3);
assert(values.any((v) => v.contains('Waikiki')));
关于 Map 的更多信息请参考Generics and Maps以及 Map API reference
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
信息。 codeUnitAt
和 codeUnit
属性返回 16-bit code units
。 使用 runes
属性来获取字符串的 runes 信息。
下面是示例演示了 runes、 16-bit code units、和 32-bit code points 之间的关系
main() {
var clapping = '\u{1f44f}';
print(clapping);
print(clapping.codeUnits);
print(clapping.runes.toList());
Runes input = new Runes(
'\u2665 \u{1f605} \u{1f60e} \u{1f47b} \u{1f596} \u{1f44d}');
print(new String.fromCharCodes(input));
注意: 使用 list
操作 runes
的时候请小心。 根据所操作的语种、字符集等, 这种操作方式可能导致你的字符串出问题。 更多信息参考 Stack Overflow 上的一个问题:How do I reverse a String in Dart?
Symbols
一个 Symbol 对象代表Dart
程序中声明的操作符或者标识符。 你也许从来不会用到 Symbol,但是该功能对于通过名字来引用标识符的情况是非常有价值的,特别是混淆后的代码, 标识符的名字被混淆了,但是Symbol
的名字不会改变。
使用 Symbol
字面量来获取标识符的symbol
对象,也就是在标识符前面添加一个 #
符号:
#radix
#bar
Symbol
字面量定义是编译时常量。