现在位置: 首页 > Dart 教程 > 正文

Dart 变量与数据类型

变量是程序中存储数据的基本单元,数据类型决定了变量能存储什么值。

本章介绍 Dart 中的变量声明方式、基本数据类型以及重要的空安全机制。


变量的声明方式:var、final、const

Dart 提供了三种声明变量的关键字,分别适用于不同的场景。

理解它们的区别是学好 Dart 的第一步。

var——类型推断变量

使用 var 声明的变量,类型由初始值自动推断,且类型一旦确定就不能更改。

实例

void main() {
  // 类型推断:name 的类型被推断为 String
  var name = 'RUNOOB';

  // 类型推断:age 的类型被推断为 int
  var age = 10;

  print('$name 已经 $age 年了');

  // 以下写法会报错——类型确定后不能再赋其他类型的值
  // name = 123;  // 错误:不能将 int 赋值给 String
}
RUNOOB 已经 10 年了

var 不是"无类型"或"动态类型",它的类型在赋值那一刻就固定了。这和 JavaScript 的 var 完全不同。

final——运行时常量

使用 final 声明的变量只能赋值一次,但赋值时机可以延迟到运行时。

实例

void main() {
  // final 变量:一旦赋值就不能再修改
  final currentTime = DateTime.now();
  print('当前时间: $currentTime');

  // 延迟赋值也是允许的
  final String greeting;
  greeting = 'Hello, RUNOOB!';  // 第一次赋值 OK
  // greeting = 'Hello again';   // 错误:final 变量不能再次赋值

  print(greeting);
}
当前时间: 2026-06-12 10:30:00.000
Hello, RUNOOB!

const——编译时常量

const 比 final 更严格:它的值必须在编译时就能确定。

实例

void main() {
  // const 必须在编译时就能确定值
  const siteName = 'RUNOOB';
  const maxUsers = 100;

  print('站点: $siteName, 最大用户数: $maxUsers');

  // 以下写法会报错——DateTime.now() 是运行时才能确定的值
  // const currentTime = DateTime.now();  // 错误!
}
站点: RUNOOB, 最大用户数: 100

三者对比总结

关键字可修改赋值时机典型场景
var可以任意值会变化的普通变量
final不可修改运行时确定从 API 获取的配置、当前时间
const不可修改编译时确定数学常量、固定配置、颜色值

一个实用建议:默认使用 final。当你发现需要修改它时,再改为 var。这个习惯能让代码更安全,减少意外修改导致的 bug。


数字类型:int 与 double

Dart 的数字类型分为两种:int(整数)和 double(浮点数)。

它们的共同父类是 num。

实例

void main() {
  // int:整数,范围是 -2^63 到 2^63-1
  int viewCount = 10000;
  int negativeNumber = -42;

  // double:双精度浮点数
  double price = 9.99;
  double pi = 3.1415926;

  // num 可以同时接收 int 和 double
  num someNumber = 10;
  someNumber = 10.5;  // 合法

  print('浏览次数: $viewCount');
  print('价格: ¥$price');
  print('圆周率: $pi');
}
浏览次数: 10000
价格: ¥9.99
圆周率: 3.1415926

数字常用方法

实例

import 'dart:math';  // 导入数学库

void main() {
  int a = -10;
  double b = 3.7;

  // 绝对值
  print('a 的绝对值: ${a.abs()}');   // 10

  // 四舍五入取整
  print('b 四舍五入: ${b.round()}');  // 4

  // 向下取整
  print('b 向下取整: ${b.floor()}');  // 3

  // 向上取整
  print('b 向上取整: ${b.ceil()}');   // 4

  // 字符串转数字
  int parsed = int.parse('42');
  double parsedDouble = double.parse('3.14');
  print('解析结果: $parsed, $parsedDouble');

  // 生成随机数(需要 import 'dart:math')
  var random = Random().nextInt(100);
  print('随机数(0-99): $random');
}
a 的绝对值: 10
b 四舍五入: 4
b 向下取整: 3
b 向上取整: 4
解析结果: 42, 3.14
随机数(0-99): 67

字符串:String 与插值语法

String 用于表示文本,Dart 的字符串支持单引号和双引号两种写法。

字符串插值(String Interpolation)是 Dart 最方便的特性之一。

实例

void main() {
  // 字符串可以用单引号或双引号
  String singleQuoted = 'Hello';
  String doubleQuoted = "World";

  // 多行字符串:使用三个引号
  String multiLine = '''
  这是第一行
  这是第二行
  这是第三行 - RUNOOB
  '
'';

  // 字符串插值:使用 $变量名 或 ${表达式}
  String site = 'RUNOOB';
  int years = 10;

  // $变量名:直接引用变量
  print('欢迎来到 $site');

  // ${表达式}:嵌入复杂表达式
  print('$site 已经陪伴我们 ${years + 1} 年了');

  // 转义字符
  print('换行符: 第一行\n第二行');
  print('制表符: 列1\t列2');
}
欢迎来到 RUNOOB
RUNOOB 已经陪伴我们 11 年了
换行符: 第一行
第二行
制表符: 列1	列2

字符串常用方法

实例

void main() {
  String text = '  Hello, RUNOOB!  ';

  // 去除首尾空格
  print('trim: [${text.trim()}]');

  // 转大写 / 转小写
  print('大写: ${text.toUpperCase()}');
  print('小写: ${text.toLowerCase()}');

  // 是否包含某个子串
  print('包含 RUNOOB? ${text.contains('RUNOOB')}');

  // 是否以某字符串开头/结尾
  print('以空格开头? ${text.startsWith(' ')}');
  print('以!结尾? ${text.trim().endsWith('!')}');

  // 字符串替换
  print('替换: ${text.replaceAll('RUNOOB', 'DART')}');

  // 字符串分割
  String csv = 'Dart,Flutter,Google';
  List<String> items = csv.split(',');
  print('分割结果: $items');

  // 字符串拼接
  print('拼接: ' + 'Hello' + ', ' + 'World');
}
trim: [Hello, RUNOOB!]
大写:   HELLO, RUNOOB!
小写:   hello, runoob!
包含 RUNOOB? true
以空格开头? true
以!结尾? true
替换:   Hello, DART!
分割结果: [Dart, Flutter, Google]
拼接: Hello, World

布尔值 bool

bool 类型只有两个值:true 和 false。

它主要用于条件判断,配合 if 语句使用。

实例

void main() {
  bool isLoggedIn = true;
  bool hasPermission = false;

  // 布尔表达式
  bool canAccess = isLoggedIn && hasPermission;  // 与:两者都为 true
  bool isGuest = !isLoggedIn;                    // 非:取反

  print('可以访问: $canAccess');
  print('是访客: $isGuest');

  // 比较运算产生 bool 值
  int age = 20;
  bool isAdult = age >= 18;
  print('是否成年: $isAdult');

  // 直接用于条件判断
  if (isAdult) {
    print('欢迎访问 RUNOOB');
  }
}
可以访问: false
是访客: false
是否成年: true
欢迎访问 RUNOOB

Dart 是强类型语言,条件判断中只接受 bool 类型。这和 JavaScript 不同——在 Dart 中,if(0) 或 if('') 这样的写法会直接报错。


空安全(Null Safety)

空安全是 Dart 2.12 引入的最重要特性。

它的核心思想是:默认情况下,所有变量都不能为 null,除非你明确声明。

可空类型与非空类型

在类型后面加 ? 表示该变量可以为 null。

实例

void main() {
  // 非空类型:不能赋值为 null
  String name = 'RUNOOB';
  // name = null;  // 错误!name 不能为 null

  // 可空类型:允许为 null
  String? nickname;
  nickname = null;  // OK
  nickname = 'R';   // 也 OK

  print('昵称: $nickname');

  // int? 也可空
  int? score;
  print('分数: $score');  // 输出 null
}
昵称: R
分数: null

空值处理操作符

操作符说明示例
??如果左侧为 null,使用右侧值name ?? '默认名'
??=如果变量为 null,则赋值为右侧name ??= '默认名'
?.安全访问:对象为 null 时跳过调用user?.name
!断言非 null(谨慎使用)name!

实例

void main() {
  String? username;

  // ?? 操作符:如果 username 为 null,使用默认值
  String displayName = username ?? 'RUNOOB 访客';
  print(displayName);  // RUNOOB 访客

  // ??= 操作符:如果为 null 则赋值
  username ??= '新用户';
  print(username);  // 新用户

  // ?. 安全访问:只在非 null 时调用
  String? maybeNull;
  print(maybeNull?.length);  // null(不会报错)

  maybeNull = 'Hello';
  print(maybeNull?.length);  // 5

  // ! 断言:我确定它不是 null(为 null 时会抛异常)
  String definitelyNotNull = 'RUNOOB';
  print(definitelyNotNull!.length);  // 6
}
RUNOOB 访客
新用户
null
5
6

尽量避免使用 ! 断言操作符。如果你频繁使用 !,说明你的类型设计可能有问题。优先使用 ??、??= 和 ?. 来安全地处理空值。


类型转换

在 Dart 中,不同类型的值可以相互转换。

实例

void main() {
  // 数字 → 字符串
  int count = 42;
  String countStr = count.toString();
  print('数字转字符串: $countStr (类型: ${countStr.runtimeType})');

  // 字符串 → 数字
  String priceStr = '19.99';
  double price = double.parse(priceStr);
  print('字符串转数字: ¥$price');

  // int ↔ double
  int integer = 10;
  double decimal = integer.toDouble();
  print('int 转 double: $decimal');

  double pi = 3.14;
  int piInt = pi.toInt();  // 截断小数部分
  print('double 转 int (截断): $piInt');

  // 任何值 → 字符串
  bool flag = true;
  print('bool 转字符串: ${flag.toString()}');

  // 字符串 → bool(需要手动判断)
  String boolStr = 'true';
  bool parsed = boolStr == 'true';
  print('字符串转 bool: $parsed');
}
数字转字符串: 42 (类型: String)
字符串转数字: ¥19.99
int 转 double: 10.0
double 转 int (截断): 3
bool 转字符串: true
字符串转 bool: true