Skip to content

内置类型
Dart 语言对以下类型提供特殊支持:

  • 数值(int、double)
  • 字符串(String)
  • 布尔值(bool)
  • 记录((value1, value2))
  • 函数(Function)
  • 列表(List,也称为数组)
  • 集合(Set)
  • 映射(Map)
  • 符文(Runes;常被 characters API 替代)
  • 符号(Symbol)
  • 空值(Null)

这种支持包括使用字面量创建对象的能力。例如,'this is a string' 是字符串字面量,true 是布尔字面量。

由于 Dart 中的每个变量都指向一个对象(类的实例),因此通常可以使用构造函数初始化变量。部分内置类型有自己的构造函数,例如可使用 Map() 构造函数创建映射。

Dart 语言中还有一些其他类型具有特殊作用:

  • Object:除 Null 外所有 Dart 类的超类。
  • Enum:所有枚举的超类。
  • Future 和 Stream:用于异步编程。
  • Iterable:用于 for-in 循环和同步生成器函数。
  • Never:表示表达式永远无法成功完成求值,最常用于始终抛出异常的函数。
  • dynamic:表示希望禁用静态检查,通常应改用 ObjectObject?
  • void:表示值永远不会被使用,常用于作为返回类型。

Object、Object?、Null 和 Never 类在类层次结构中具有特殊作用,可在《理解空安全》中了解这些作用。

数值

Dart 数值有两种类型:

int

整数数值,根据平台不同,最大不超过 64 位。

  • 在原生平台上,值范围为 -2⁶³2⁶³ - 1
  • 在 Web 上,整数值表示为 JavaScript 数字(无小数部分的 64 位浮点值),范围为 -2⁵³2⁵³ - 1

double

64 位(双精度)浮点数值,符合 IEEE 754 标准。

intdouble 都是 num 的子类型。num 类型包含 +-/* 等基本运算符,还提供 abs()ceil()floor() 等方法(按位运算符如 >>int 类中定义)。如果 num 及其子类型未提供所需功能,可使用 dart:math 库。

整数是不带小数点的数值,以下是定义整数字面量的示例:

dart
var x = 1;  
var hex = 0xDEADBEEF;

如果数值包含小数点,则为 double 类型,以下是定义双精度字面量的示例:

dart
var y = 1.1;  
var exponents = 1.42e5;

也可将变量声明为 num,此时变量可存储整数和双精度值:

dart
num x = 1; // x 可存储 int 和 double 值  
x += 2.5;

必要时,整数字面量会自动转换为双精度值:

dart
double z = 1; // 等效于 double z = 1.0

以下是字符串与数值相互转换的示例:

dart
// 字符串 -> int  
var one = int.parse('1');  
assert(one == 1);  

// 字符串 -> double  
var onePointOne = double.parse('1.1');  
assert(onePointOne == 1.1);  

// int -> 字符串  
String oneAsString = 1.toString();  
assert(oneAsString == '1');  

// double -> 字符串  
String piAsString = 3.14159.toStringAsFixed(2);  
assert(piAsString == '3.14');

int 类型支持传统的按位移位(<<>>>>>)、取反(~)、与(&)、或(|)和异或(^)运算符,适用于操作位字段中的标志和掩码。例如:

dart
assert((3 << 1) == 6); // 0011 << 1 == 0110  
assert((3 | 4) == 7); // 0011 | 0100 == 0111  
assert((3 & 4) == 0); // 0011 & 0100 == 0000

更多示例请参见按位和移位运算符部分。

数值字面量是编译时常量,只要操作数是计算结果为数值的编译时常量,许多算术表达式也是编译时常量:

dart
const msPerSecond = 1000;  
const secondsUntilRetry = 5;  
const msUntilRetry = secondsUntilRetry * msPerSecond;

更多信息请参见《Dart 中的数值》。

可使用一个或多个下划线(_)作为数字分隔符,提高长数值字面量的可读性,多个分隔符支持更高级别的分组:

dart
var n1 = 1_000_000;  
var n2 = 0.000_000_000_01;  
var n3 = 0x00_14_22_01_23_45; // MAC 地址  
var n4 = 555_123_4567; // 美国电话号码  
var n5 = 100__000_000__000_000; // 一百万亿!

版本说明:使用数字分隔符需要语言版本至少为 3.6。

字符串

Dart 字符串(String 对象)存储一系列 UTF-16 代码单元。可使用单引号或双引号创建字符串:

dart
var s1 = '单引号适用于字符串字面量。';  
var s2 = "双引号同样适用。";  
var s3 = '转义字符串定界符很简单:\'。';  
var s4 = "使用另一种定界符更简单。";

可通过 ${表达式} 将表达式的值嵌入字符串中。如果表达式是标识符,可省略 {}。Dart 会调用对象的 toString() 方法获取其对应的字符串。

dart
var s = '字符串插值';  

assert(  
  'Dart 支持 $s,非常方便。' ==  
      'Dart 支持字符串插值,非常方便。',  
);  
assert(  
  '这值得全部大写。${s.toUpperCase()} 非常方便!' ==  
      '这值得全部大写。STRING INTERPOLATION 非常方便!',  
);

注意== 运算符用于测试两个对象是否等价,两个字符串包含相同的代码单元序列时即为等价。

可通过相邻字符串字面量或 + 运算符拼接字符串:

dart
var s1 =  
    '字符串 '  
    '拼接'  
    "即使跨越多行也有效。";  
assert(  
  s1 ==  
      '字符串拼接即使跨越 '  
          '行也有效。',  
);  

var s2 = '+ 运算符 ' + '同样有效。';  
assert(s2 == '+ 运算符同样有效。');

使用三引号(单引号或双引号)创建多行字符串:

dart
var s1 = '''  
你可以像这样创建  
多行字符串。  
''';  

var s2 = """这也是  
多行字符串。""";

在字符串前添加 r 前缀可创建“原始”字符串,其中转义符不会被特殊处理:

dart
var s = r'在原始字符串中,即使 \n 也不会被特殊处理。';

有关如何在字符串中表示 Unicode 字符的详细信息,请参见《符文和字素簇》。

只要插值表达式是计算结果为 null、数值、字符串或布尔值的编译时常量,字符串字面量就是编译时常量:

dart
// 这些可在 const 字符串中使用  
const aConstNum = 0;  
const aConstBool = true;  
const aConstString = '常量字符串';  

// 这些不可在 const 字符串中使用  
var aNum = 0;  
var aBool = true;  
var aString = '字符串';  
const aConstList = [1, 2, 3];  

const validConstString = '$aConstNum $aConstBool $aConstString';  
// const invalidConstString = '$aNum $aBool $aString $aConstList';

有关字符串使用的更多信息,请参见《字符串和正则表达式》。

布尔值

Dart 使用名为 bool 的类型表示布尔值,只有两个对象属于 bool 类型:布尔字面量 truefalse,二者均为编译时常量。

Dart 的类型安全机制意味着不能使用类似 if (nonbooleanValue)assert(nonbooleanValue) 的代码,而应显式检查值,例如:

dart
// 检查空字符串  
var fullName = '';  
assert(fullName.isEmpty);  

// 检查零值  
var hitPoints = 0;  
assert(hitPoints == 0);  

// 检查 null  
var unicorn = null;  
assert(unicorn == null);  

// 检查 NaN  
var iMeantToDoThis = 0 / 0;  
assert(iMeantToDoThis.isNaN);

符文和字素簇

在 Dart 中,runes 用于暴露字符串的 Unicode 代码点。可使用 characters 包查看或操作用户感知的字符(也称为 Unicode 扩展字素簇)。

Unicode 为世界上所有书写系统中的每个字母、数字和符号定义了唯一的数值。由于 Dart 字符串是 UTF-16 代码单元的序列,因此在字符串中表示 Unicode 代码点需要特殊语法。通常使用 \uXXXX 表示 Unicode 代码点,其中 XXXX 是 4 位十六进制值。例如,心形字符(♥)表示为 \u2665。若需要指定多于或少于 4 位的十六进制值,可将值放在大括号中,例如笑脸表情符号(😆)表示为 \u{1f606}

如果需要读取或写入单个 Unicode 字符,可使用 characters 包在 String 上定义的 characters getter,返回的 Characters 对象将字符串视为字素簇序列。以下是使用 characters API 的示例:

dart
import 'package:characters/characters.dart';  

void main() {  
  var hi = 'Hi 🇩🇰';  
  print(hi);  
  print('字符串末尾:${hi.substring(hi.length - 1)}');  
  print('最后一个字符:${hi.characters.last}');  
}

根据环境不同,输出可能如下:

dart run bin/main.dart  
Hi 🇩🇰  
字符串末尾:???  
最后一个字符:🇩🇰

有关使用 characters 包操作字符串的详细信息,请参见该包的示例和 API 参考。

符号

Symbol 对象表示 Dart 程序中声明的运算符或标识符。可能永远不需要使用符号,但对于按名称引用标识符的 API 而言,符号非常重要,因为代码压缩会改变标识符名称,但不会改变标识符的符号。

要获取标识符的符号,可使用符号字面量,即 # 后跟标识符:

dart
#radix  
#bar

符号字面量是编译时常量。