dart面试题

Dart 面试题与参考答案

适合 Flutter/Dart 面试复习。内容覆盖 Dart 基础语法、类型系统、空安全、面向对象、异步机制、集合、函数、扩展能力、并发模型和工程实践。

一、Dart 基础

1. Dart 是什么?

Dart 是 Google 推出的编程语言,常用于 Flutter 应用开发。它支持面向对象、泛型、空安全、异步编程和 AOT/JIT 编译。

Dart 在 Flutter 中主要负责:

  • 编写业务逻辑。
  • 描述 UI。
  • 管理状态。
  • 调用平台能力。

2. Dart 和 JavaScript 有什么区别?

Dart 是强类型语言,支持静态类型检查;JavaScript 是动态类型语言。

Dart 支持 JIT 和 AOT 编译,Flutter 开发阶段使用 JIT 支持热重载,发布阶段使用 AOT 提升性能。

JavaScript 主要运行在浏览器或 Node.js 环境中,而 Dart 在 Flutter 中可以编译到 Android、iOS、Web、桌面等平台。

3. Dart 是单线程的吗?

Dart 的主 isolate 是单线程执行的,Flutter UI 通常运行在主 isolate。

但 Dart 支持多个 isolate。每个 isolate 有独立内存,不能直接共享对象,只能通过消息通信。

4. main() 方法的作用是什么?

main() 是 Dart 程序入口。

普通 Dart 程序:

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

Flutter 应用中通常会调用:

void main() {
  runApp(const MyApp());
}

5. Dart 中变量如何声明?

常见方式:

var name = '张三';
String city = '北京';
final age = 18;
const pi = 3.14;
dynamic value = 'hello';
Object object = 'world';

var 会根据初始值推断类型,显式类型声明更适合公共 API 和需要表达清楚意图的场景。

6. finalconst 的区别?

final 表示变量只能赋值一次,值可以在运行时确定。

const 表示编译期常量,值必须在编译期确定。

final now = DateTime.now(); // 可以
const appName = 'Demo'; // 可以

不能写:

const now = DateTime.now(); // 错误

因为当前时间不是编译期常量。

7. vardynamicObject 的区别?

var 是类型推断,类型确定后不能随意改变。

var name = '张三';
name = '李四';
// name = 123; // 编译错误

dynamic 会关闭静态类型检查,运行时才知道是否正确。

dynamic value = 'hello';
value = 123;
value.notExistMethod(); // 编译可能通过,运行时报错

Object 可以接收非 null 对象,但只能使用 Object 本身的方法。

Object value = 'hello';
// value.length; // 编译错误

if (value is String) {
  print(value.length);
}

8. Dart 中 late 的作用和风险是什么?

late 表示变量稍后初始化。

late String token;

void init() {
  token = 'abc';
}

风险是:如果赋值前访问,会抛出 LateInitializationError

late String name;
print(name); // 运行时报错

9. Dart 支持哪些注释?

单行注释:

// 单行注释

多行注释:

/*
 多行注释
*/

文档注释:

/// 用户模型
class User {}

文档注释可以被 Dart 文档工具识别。

10. Dart 中字符串如何拼接?

推荐使用字符串插值:

final name = '张三';
final age = 18;

print('姓名:$name,年龄:$age');

复杂表达式使用 ${}

print('明年年龄:${age + 1}');

二、类型系统与空安全

1. Dart 的空安全是什么?

空安全用于在编译期减少空指针问题。

默认类型不可为 null:

String name = '张三';
// name = null; // 编译错误

如果允许为空,需要使用 ?

String? nickname;

2. ?!???. 分别是什么意思?

? 表示可空类型:

String? name;

! 表示强制断言非空:

print(name!.length);

如果实际为 null,会运行时报错。

?? 表示为空时使用默认值:

final displayName = name ?? '匿名用户';

?. 表示对象非空时才调用:

print(name?.length);

3. required 的作用是什么?

required 用于命名参数,表示该参数必须传入。

class User {
  final String name;
  final int age;

  const User({
    required this.name,
    required this.age,
  });
}

调用:

final user = User(name: '张三', age: 18);

4. isas 有什么区别?

is 用于类型判断:

if (value is String) {
  print(value.length);
}

as 用于类型转换:

final text = value as String;

如果转换失败,as 会抛异常。

5. runtimeType 是什么?

runtimeType 用于获取对象运行时类型。

final value = 'hello';
print(value.runtimeType); // String

调试时可以使用,但业务逻辑中不建议过度依赖 runtimeType

6. typedef 有什么用?

typedef 可以给函数类型起别名,提高可读性。

typedef ValueChanged<T> = void Function(T value);

void handle(ValueChanged<String> onChanged) {
  onChanged('hello');
}

Flutter 中很多回调类型都使用了类似思想。

7. Dart 中泛型有什么作用?

泛型用于提高类型安全和复用性。

class ApiResponse<T> {
  final int code;
  final T data;

  ApiResponse({
    required this.code,
    required this.data,
  });
}

使用:

final response = ApiResponse<User>(
  code: 0,
  data: User(name: '张三'),
);

这样 data 的类型就是 User,不需要频繁强转。

8. List<Object>List<dynamic> 有什么区别?

List<Object> 中的元素至少是非 null 对象,使用时保留静态类型检查。

List<dynamic> 中的元素可以是任意类型,调用方法时静态检查更弱。

List<Object> a = ['hello', 1];
List<dynamic> b = ['hello', 1, null];

业务代码中应尽量避免大量使用 dynamic

9. Never 类型是什么?

Never 表示函数永远不会正常返回。

例如:

Never fail(String message) {
  throw Exception(message);
}

它常用于异常、不可达分支和类型推断。

10. Dart 中 Object?Objectdynamic 如何选择?

如果值可以为任意类型且可能为 null,用 Object?

如果值可以为任意非 null 对象,用 Object

如果确实需要关闭类型检查,例如 JSON 边界数据,可以用 dynamic,但进入业务层后应尽快转成明确类型。

三、面向对象

1. Dart 是面向对象语言吗?

是。Dart 中几乎所有东西都是对象,包括数字、字符串、函数、集合等。

Dart 支持类、继承、抽象类、接口、mixin、扩展方法和泛型。

2. Dart 如何定义类?

class User {
  final String name;
  final int age;

  User(this.name, this.age);

  void sayHello() {
    print('你好,我是 $name');
  }
}

使用:

final user = User('张三', 18);
user.sayHello();

3. Dart 的构造函数有哪些写法?

普通构造函数:

class User {
  final String name;

  User(this.name);
}

命名构造函数:

class User {
  final String name;

  User(this.name);

  User.guest() : name = '游客';
}

工厂构造函数:

class User {
  final String name;

  User(this.name);

  factory User.fromJson(Map<String, dynamic> json) {
    return User(json['name'] as String);
  }
}

4. factory 构造函数有什么特点?

factory 构造函数不一定创建新对象,可以返回已有对象、子类对象或缓存对象。

class Logger {
  static final Logger _instance = Logger._internal();

  Logger._internal();

  factory Logger() {
    return _instance;
  }
}

适合单例、缓存和复杂对象创建。

5. Dart 如何继承?

使用 extends

class Animal {
  void eat() {
    print('吃东西');
  }
}

class Dog extends Animal {
  void bark() {
    print('汪汪');
  }
}

Dog 可以调用 eat()bark()

6. super 的作用是什么?

super 用于调用父类构造函数、方法或属性。

class Person {
  final String name;

  Person(this.name);
}

class Student extends Person {
  final String school;

  Student(String name, this.school) : super(name);
}

重写方法时也可以调用父类逻辑:

@override
void init() {
  super.init();
  print('子类初始化');
}

7. abstract class 有什么用?

抽象类用于定义通用能力或约束,不能直接实例化。

abstract class Shape {
  double area();
}

class Circle extends Shape {
  final double radius;

  Circle(this.radius);

  @override
  double area() {
    return 3.14 * radius * radius;
  }
}

8. Dart 中接口如何实现?

Dart 没有单独的 interface 关键字,普通类和抽象类都可以作为接口使用。

使用 implements

abstract class JsonSerializable {
  Map<String, dynamic> toJson();
}

class User implements JsonSerializable {
  final String name;

  User(this.name);

  @override
  Map<String, dynamic> toJson() {
    return {'name': name};
  }
}

implements 要实现接口中的所有成员。

9. extendsimplements 的区别?

extends 表示继承父类,可以复用父类实现。

implements 表示实现接口,只遵守结构约束,通常需要自己实现所有成员。

extends:我是某个父类的子类。
implements:我承诺实现某种能力。

10. mixin 是什么?

mixin 用于在不增加继承层级的情况下复用一组能力。

mixin Logger {
  void log(String message) {
    print('[Log] $message');
  }
}

class UserService with Logger {
  void login() {
    log('用户登录');
  }
}

Flutter 中常见:

class _PageState extends State<Page>
    with SingleTickerProviderStateMixin {}

11. withon 在 mixin 中有什么作用?

with 用于混入 mixin:

class Dog with RunAbility {}

on 用于限制 mixin 只能用于某类或其子类:

mixin LoadingMixin<T extends StatefulWidget> on State<T> {
  bool loading = false;

  void showLoading() {
    setState(() {
      loading = true;
    });
  }
}

这里 LoadingMixin 只能混入 State<T>,所以内部可以安全调用 setState()

12. extension 是什么?

extension 可以给已有类型扩展方法或 getter,而不修改原类型源码。

extension StringExt on String {
  bool get isPhone {
    return RegExp(r'^1\d{10}$').hasMatch(this);
  }

  String maskPhone() {
    if (length != 11) return this;
    return '${substring(0, 3)}****${substring(7)}';
  }
}

使用:

print('13800138000'.isPhone);
print('13800138000'.maskPhone());

四、函数与闭包

1. Dart 中函数是一等公民是什么意思?

函数可以像普通对象一样赋值、作为参数传递、作为返回值返回。

void sayHello() {
  print('hello');
}

final callback = sayHello;
callback();

2. 箭头函数适合什么场景?

箭头函数适合只有一个表达式的函数。

int add(int a, int b) => a + b;

等价于:

int add(int a, int b) {
  return a + b;
}

3. 位置参数和命名参数有什么区别?

位置参数按顺序传:

void login(String username, String password) {}

login('admin', '123456');

命名参数按名字传,可读性更好:

void login({
  required String username,
  required String password,
}) {}

login(username: 'admin', password: '123456');

4. 可选参数如何声明?

可选位置参数使用 []

void say(String name, [String? message]) {}

可选命名参数使用 {}

void say({
  required String name,
  String message = '你好',
}) {}

5. 闭包是什么?

闭包是函数捕获并使用其外部作用域变量的能力。

Function makeCounter() {
  int count = 0;

  return () {
    count++;
    return count;
  };
}

void main() {
  final counter = makeCounter();
  print(counter()); // 1
  print(counter()); // 2
}

内部函数捕获了外部变量 count

6. 回调函数在 Flutter 中有什么用?

回调函数用于把子组件事件通知给父组件。

class SubmitButton extends StatelessWidget {
  final VoidCallback onSubmit;

  const SubmitButton({
    super.key,
    required this.onSubmit,
  });

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: onSubmit,
      child: const Text('提交'),
    );
  }
}

7. Function 和具体函数类型有什么区别?

Function 太宽泛,类型约束弱。

不推荐:

final Function callback;

推荐:

final void Function(String value) onChanged;

或者使用 Flutter 提供的:

final ValueChanged<String> onChanged;

具体函数类型更安全、更清晰。

8. async 函数返回值是什么?

async 标记的函数会返回 Future

Future<String> fetchName() async {
  return '张三';
}

即使直接返回字符串,也会被包装成 Future<String>

9. sync*async* 是什么?

sync* 用于同步生成 Iterable:

Iterable<int> numbers() sync* {
  yield 1;
  yield 2;
  yield 3;
}

async* 用于异步生成 Stream:

Stream<int> countStream() async* {
  yield 1;
  await Future.delayed(const Duration(seconds: 1));
  yield 2;
}

10. yield 的作用是什么?

yield 用于生成一个值,但不会像 return 那样结束整个生成函数。

Iterable<int> range(int max) sync* {
  for (var i = 0; i < max; i++) {
    yield i;
  }
}

五、集合与常用操作

1. Dart 中常用集合有哪些?

常用集合:

List<String> names = ['张三', '李四'];
Set<int> ids = {1, 2, 3};
Map<String, dynamic> json = {'name': '张三'};

List 有序可重复,Set 无重复元素,Map 保存键值对。

2. List 常用方法有哪些?

常见方法:

final list = [1, 2, 3];

list.add(4);
list.remove(2);
list.contains(3);
list.map((e) => e * 2);
list.where((e) => e > 1);
list.first;
list.last;

3. mapwhereforEach 的区别?

map 用于转换:

final result = [1, 2, 3].map((e) => e * 2).toList();

where 用于过滤:

final result = [1, 2, 3].where((e) => e > 1).toList();

forEach 用于遍历执行副作用:

[1, 2, 3].forEach(print);

4. IterableList 有什么区别?

Iterable 表示可迭代对象,不一定支持下标访问。

List 是有序集合,支持下标访问和长度。

很多集合操作如 mapwhere 返回的是 Iterable,如果需要列表,要调用:

toList()

5. Set 有什么特点?

Set 不允许重复元素。

final ids = {1, 2, 2, 3};
print(ids); // {1, 2, 3}

适合去重、成员判断等场景。

6. Map 如何遍历?

final user = {
  'name': '张三',
  'age': 18,
};

user.forEach((key, value) {
  print('$key: $value');
});

也可以:

for (final entry in user.entries) {
  print('${entry.key}: ${entry.value}');
}

7. Dart 中扩展运算符 ... 有什么用?

用于展开集合:

final a = [1, 2];
final b = [0, ...a, 3];
print(b); // [0, 1, 2, 3]

可空展开使用 ...?

List<int>? a;
final b = [0, ...?a, 3];

8. collection if 和 collection for 是什么?

集合中可以直接写条件和循环。

final isLogin = true;

final menus = [
  '首页',
  if (isLogin) '个人中心',
];

循环:

final widgets = [
  for (final item in items) Text(item.title),
];

Flutter UI 中非常常用。

9. 如何避免访问空列表报错?

不要直接对可能为空的列表调用 first

可以判断:

if (list.isNotEmpty) {
  print(list.first);
}

也可以封装扩展:

extension IterableExt<T> on Iterable<T> {
  T? get firstOrNull {
    if (isEmpty) return null;
    return first;
  }
}

10. 如何将 JSON 转成 Dart Model?

手写:

class User {
  final String name;
  final int age;

  User({
    required this.name,
    required this.age,
  });

  factory User.fromJson(Map<String, dynamic> json) {
    return User(
      name: json['name'] as String,
      age: json['age'] as int,
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'name': name,
      'age': age,
    };
  }
}

大型项目常使用 json_serializable 或 freezed 生成代码。

六、异步编程

1. Future 是什么?

Future 表示未来某个时间完成的一次异步结果。

Future<String> fetchName() async {
  await Future.delayed(const Duration(seconds: 1));
  return '张三';
}

适合网络请求、文件读取、数据库查询等一次性异步任务。

2. Stream 是什么?

Stream 表示一系列异步事件。

Stream<int> countStream() async* {
  yield 1;
  yield 2;
  yield 3;
}

适合聊天消息、定位更新、下载进度、WebSocket、计时器等连续事件。

3. Future 和 Stream 的区别?

Future 是一次结果。

Stream 是多次结果。

Future:一次网络请求。
Stream:持续接收消息。

4. async / await 的作用是什么?

async 让函数返回 Future

await 等待异步任务完成后继续执行,不会阻塞 UI 线程。

Future<void> load() async {
  final user = await fetchUser();
  print(user.name);
}

5. 如何捕获异步异常?

使用 try-catch

try {
  final user = await fetchUser();
  print(user.name);
} catch (e, stackTrace) {
  print(e);
}

也可以使用:

fetchUser().catchError((error) {
  print(error);
});

6. Dart 事件循环执行顺序是什么?

通常顺序:

同步代码
Microtask Queue
Event Queue

示例:

void main() {
  print('1');

  Future(() => print('2 Future'));
  Future.microtask(() => print('3 Microtask'));

  print('4');
}

输出:

1
4
3 Microtask
2 Future

7. Microtask 和 Event Queue 有什么区别?

Microtask 优先级更高,会在当前同步代码结束后、Event Queue 之前执行。

普通 Future(() {})、Timer、I/O、用户事件通常进入 Event Queue。

如果不断创建 Microtask,可能导致 Event Queue 长时间得不到执行。

8. Future.microtaskFuture(() {}) 的区别?

Future.microtask 进入 Microtask Queue。

Future(() {}) 进入 Event Queue。

Future.microtask(() => print('microtask'));
Future(() => print('event'));

microtask 通常先输出。

9. StreamController 有什么作用?

StreamController 用于手动创建和控制 Stream。

final controller = StreamController<int>();

controller.stream.listen((value) {
  print(value);
});

controller.add(1);
controller.add(2);
await controller.close();

注意使用完成后要 close(),避免资源泄漏。

10. await for 有什么用?

await for 用于异步遍历 Stream。

await for (final value in countStream()) {
  print(value);
}

它会等待每个事件到来并依次处理。

11. isolate 是什么?

isolate 是 Dart 的并发执行单元,每个 isolate 拥有独立内存。

主 isolate 通常负责 UI,耗时计算可以放到其他 isolate,避免阻塞界面。

final result = await Isolate.run(() {
  return heavyCalculate();
});

12. isolate 和线程有什么区别?

线程通常可以共享内存,需要锁处理并发问题。

isolate 不共享内存,只能通过消息通信,因此减少了共享内存带来的数据竞争问题。

七、相等性与对象身份

1. ==identical() 的区别?

== 判断相等性,可以被重写。

identical() 判断是否是同一个对象引用。

class User {
  final String name;

  User(this.name);
}

void main() {
  final a = User('张三');
  final b = User('张三');
  final c = a;

  print(a == b); // false,未重写 ==
  print(identical(a, b)); // false
  print(identical(a, c)); // true
}

2. 如何重写 ==

class User {
  final String name;

  User(this.name);

  @override
  bool operator ==(Object other) {
    return other is User && other.name == name;
  }

  @override
  int get hashCode => name.hashCode;
}

重写 == 时必须同时重写 hashCode

3. 为什么重写 == 要同时重写 hashCode

因为 SetMap 等哈希集合依赖 hashCode 查找对象。

如果两个对象 == 为 true,但 hashCode 不一致,会导致集合行为异常。

4. const 对象和 identical() 有什么关系?

相同参数的 const 对象可能被规范化为同一个实例。

class User {
  final String name;

  const User(this.name);
}

void main() {
  const a = User('张三');
  const b = User('张三');

  print(identical(a, b)); // true
}

非 const 创建通常是不同实例。

5. 什么是不可变对象?

不可变对象创建后内部状态不能改变。

class User {
  final String name;
  final int age;

  const User({
    required this.name,
    required this.age,
  });
}

不可变对象更适合状态管理、缓存、比较和多处共享。

八、Dart 与 Flutter 实战问题

1. 为什么 Flutter 中推荐使用 const

const 可以创建编译期常量对象,减少重复创建 Widget 配置对象。

在 Flutter 中:

const Text('固定文字')

如果参数不变,多次 build 可以复用同一个 Widget 实例,降低更新成本。

2. mounted 有什么用?

mounted 表示当前 State 是否仍然挂载在 Widget 树上。

异步后如果要调用 setState() 或使用 context,应判断:

if (!mounted) return;

setState(() {
  loading = false;
});

避免页面销毁后继续更新 UI。

3. 为什么不建议在 build() 中做耗时操作?

build() 可能频繁执行。

如果在里面做网络请求、复杂计算或创建重量级对象,会造成性能问题和重复请求。

耗时逻辑应放到状态层、initState()、异步任务或 isolate 中。

4. Dart 如何区分开发和生产环境配置?

可以使用 --dart-define

flutter run --dart-define=ENV=dev
flutter build apk --dart-define=ENV=prod

代码中读取:

class Env {
  static const env = String.fromEnvironment(
    'ENV',
    defaultValue: 'dev',
  );
}

5. String.fromEnvironment 是运行时读取吗?

不是。它读取的是编译期环境常量。

打包后值已经确定,不能在 App 运行过程中动态改变。

6. JSON 中为什么常用 Map<String, dynamic>

因为 JSON 的 value 可能是字符串、数字、布尔值、数组、对象或 null。

final Map<String, dynamic> json = {
  'name': '张三',
  'age': 18,
  'vip': true,
};

但业务层不建议长期使用 dynamic,应尽快转成明确 Model。

7. 如何避免 Dart 中的运行时类型错误?

常见方式:

  • 尽量使用明确类型。
  • 减少 dynamic
  • JSON 转 Model。
  • 使用泛型。
  • 使用 is 判断后再使用。
  • 避免滥用 as 强转。

8. Dart 中如何实现单例?

常见写法:

class AppConfig {
  AppConfig._internal();

  static final AppConfig instance = AppConfig._internal();
}

也可以使用 factory

class Logger {
  static final Logger _instance = Logger._internal();

  Logger._internal();

  factory Logger() => _instance;
}

9. Dart 中如何处理资源释放?

需要手动关闭或释放的资源,应在合适生命周期中处理。

例如:

final controller = StreamController<int>();

void dispose() {
  controller.close();
}

Flutter 中常见需要释放:

  • TextEditingController
  • ScrollController
  • AnimationController
  • FocusNode
  • Stream 订阅
  • Timer

10. Dart 中如何做代码生成?

常见工具:

  • build_runner
  • json_serializable
  • freezed
  • retrofit

常见命令:

flutter pub run build_runner build

或:

dart run build_runner build

如果遇到冲突文件:

dart run build_runner build --delete-conflicting-outputs

九、高频追问题

1. Dart 为什么适合 Flutter?

Dart 同时支持 JIT 和 AOT。

开发阶段使用 JIT 支持热重载,发布阶段使用 AOT 编译成机器码提升性能。

同时 Dart 的声明式 UI 写法、异步模型、空安全和强类型系统都适合构建 Flutter 应用。

2. AOT 和 JIT 的区别?

JIT(Just In Time)是运行时编译,适合开发调试和热重载。

AOT(Ahead Of Time)是提前编译,适合发布模式,启动更快、运行性能更好。

debug:JIT,开发效率高。
release:AOT,性能更好。

3. Dart 的事件循环为什么重要?

Flutter UI 在主 isolate 上运行。如果主 isolate 被耗时同步任务阻塞,界面就会卡顿。

理解同步代码、Microtask Queue 和 Event Queue 的顺序,有助于分析异步执行顺序和 UI 卡顿问题。

4. 什么时候使用 isolate?

当任务是 CPU 密集型,并且可能阻塞 UI 时,可以考虑 isolate。

例如:

  • 大 JSON 解析。
  • 图片处理。
  • 加密计算。
  • 大量数据排序。

普通网络请求通常不需要 isolate,因为它本身就是异步 I/O。

5. Dart 中如何写出更安全的代码?

建议:

  • 使用空安全。
  • 使用明确类型。
  • 少用 dynamic
  • 优先不可变对象。
  • 异步后检查 mounted
  • 捕获异常并上报。
  • 对外部输入做校验。
  • 使用单元测试覆盖核心逻辑。

6. dynamic 可以不用吗?

不能完全不用。JSON、平台通道、第三方动态数据中经常会遇到 dynamic

但应该把 dynamic 限制在边界层,进入业务逻辑前转成明确类型。

7. 为什么推荐 Model 使用 final 字段?

final 字段让对象更接近不可变,减少被意外修改的风险。

状态更新时通常创建新对象,而不是直接改旧对象,这有利于状态管理和 UI 更新判断。

8. copyWith 有什么用?

copyWith 用于基于旧对象创建一个修改部分字段的新对象。

class User {
  final String name;
  final int age;

  const User({
    required this.name,
    required this.age,
  });

  User copyWith({
    String? name,
    int? age,
  }) {
    return User(
      name: name ?? this.name,
      age: age ?? this.age,
    );
  }
}

使用:

final user = User(name: '张三', age: 18);
final newUser = user.copyWith(age: 19);

9. Dart 中异常如何处理?

使用 try-catch-finally

try {
  await request();
} catch (e, stackTrace) {
  print(e);
} finally {
  print('结束');
}

可以抛出异常:

throw Exception('请求失败');

10. 面试中如何回答 Dart 的核心优势?

可以这样回答:

Dart 是一门适合 Flutter 的现代强类型语言,支持空安全、泛型、异步编程、扩展方法、mixin 和 AOT/JIT 编译。开发阶段 JIT 支持热重载,发布阶段 AOT 编译提升性能。它的语法和声明式 UI 风格结合得很好,同时强类型和空安全能减少大量运行时错误。

十、复习建议

建议优先掌握:

  • finalconstvardynamicObject
  • 空安全:?!???.
  • 类、继承、抽象类、接口、mixin、extension。
  • Future、Stream、async/await、事件循环。
  • List、Map、Set 和常用集合操作。
  • ==hashCodeidentical()
  • AOT/JIT、isolate、--dart-define

如果时间有限,优先把「类型系统」「空安全」「异步机制」「面向对象」「Dart 与 Flutter 的关系」讲清楚,面试命中率最高。

posted @ 2026-06-24 14:23  呢哇哦比较  阅读(22)  评论(0)    收藏  举报