Skip to content

⚠️ 阅读前提示:本文包含大量隐藏技巧和容易被忽视的细节!建议配合官方文档食用


目录

  1. 基础类型
    • 1.1 数字类型
    • 1.2 字符串类型
    • 1.3 布尔类型
  2. 动态类型
  3. 集合类型
  4. 空安全与类型推断陷阱
  5. 类型检查与转换

1. 基础类型

1.1 数字类型

  • int:不仅是整数,还支持不同进制表示

    dart
    int hex = 0xDEADBEEF; // 十六进制
    int binary = 0b1101101; // 二进制(新手容易写错前导0b)
  • double:浮点数陷阱

    dart
    double a = 1;    // ✅ 自动转换为1.0
    int b = 2.0;     // ❌ 编译报错!(新手常见错误)

易忽略点

  • int 和 double 都是 num 的子类型,但自动转换只有 double → num 允许
  • 使用 整数.toDouble() 显式转换更安全
方法描述示例
floor()向下取整3.9.floor() → 3
ceil()向上取整3.1.ceil() → 4
round()四舍五入3.5.round() → 4

1.2 字符串类型

  • 单引号 vs 双引号:Dart中两者等价,但要注意嵌套使用

    dart
    String s1 = 'It\'s a book'; // 正确转义
    String s2 = "It's easier"; // 更优方案
  • 三引号的妙用(新手极少用但实用):

    dart
    String poem = '''
    床前明月光,
    疑是地上霜。
    '''; // 自动保留换行和缩进格式

💡 字符串插值隐藏规则

  • 只有表达式才能用 ${...},语句不可用
    dart
    '结果是${a + b}'   // ✅
    '数值是${if(a>0) a else b}'  // ❌(控制流语句不能放在插值中)

1.3 布尔类型

Dart 的严格规则(与JavaScript不同):

  • 只有 truefalse 才视为布尔值
  • 其他类型(如0、空字符串、空集合)不会隐式转换

🚨 错误案例:

dart
if ('') { /* 不会执行 */ }         // **错误!** 编译不通过
var visible = 'true';            // 类型是String!
if (visible) { ... }             // 类型不匹配错误

2. 动态类型

dynamic vs var(新手易混淆概念):

dart
dynamic a = 'Hello';
a = 10;   // ✅ 允许修改类型

var b = 'World';
b = 100;  // ❌ 类型已被推断为String

⚠️ 使用建议

  • 避免滥用dynamic,会失去类型安全检查优势
  • 在需要后期确定类型时,优先使用 Object?

3. 集合类型

3.1 List底层机制

创建List的三种方式与区别

dart
var list1 = [1, 2, 3];          // 推断为List<int>
List<dynamic> list2 = [1, 'a']; // 动态类型列表
var list3 = List.filled(5, ''); // 定长列表(新手常忘记长度不可变)

💥 展开操作符的陷阱

dart
var list = [1, 2];
var newList = [...?list];  // 空安全操作符(当list为null时自动处理)

3.2 Map关键特性

键值类型一致性规则

dart
Map<String, int> age = {
  'Alice': 20,
  20: 30      // ❌ 类型不匹配!(错误很隐蔽)
};

💡 遍历技巧(新手常遗漏):

dart
map.forEach((k,v) => print('$k : $v'));

3.3 Set的独特性质

  • 自动去重机制基于哈希码
  • 可以用于快速判断包含关系
dart
var set = {1, 2, 3};
print(set.contains(2));  // true(比List判断效率高)

4. 空安全与类型推断陷阱

不可忽视的代码规范

dart
int a;             // ❌ 非空变量必须初始化
int? b;            // ✅ 可空变量允许后期赋值

late int c;        // 延迟初始化(新手易误用作可空替代)

🔥 类型推断的特殊情况

dart
var list = [];
list.add(1);       // 实际类型为List<dynamic>!
list.add('a');     // 允许但危险(应指定泛型)

5. 类型检查与转换

安全转换秘诀

dart
// 危险方式
String s = 123 as String; // 可能抛出异常

// 安全方式
if (123 is String) {      // 先检查类型
  // 不会执行到这里
}

// 安全转换方法
num n = 3.14;
double d = n.toDouble();  // 最佳实践

🌟 推荐工具方法

dart
dynamic value = GetUserInput();

// 泛型类型检查扩展方法(避免重复代码)
T safeCast<T>(dynamic value, [T? defaultValue]) {
  return value is T ? value : defaultValue ?? T();
}

总结要点

  1. Dart是强类型语言,但有灵活的推断机制
  2. 空安全是编译时的强力保障,不是运行时检查
  3. 集合类型的泛型参数至关重要
  4. 合理使用类型转换避免运行时错误

延伸思考问题

  • 为什么 const Object arr = [1,2,3] 会被Dart拒绝?
  • 当混合使用numint时可能遇到哪些隐蔽问题?
  • 如何通过泛型实现类型安全的空列表创建?