Skip to content

第12章:Dart 异常处理(实战必备)

12.1 异常的概念

异常是程序运行过程中出现的错误,它会导致程序的正常执行流程被中断。在 Dart 中,异常是一个对象,通常是 ExceptionError 的子类。

异常处理的目的是:

  • 捕获并处理异常,避免程序崩溃
  • 提供友好的错误提示
  • 保证程序的健壮性和可靠性

12.2 Dart 中常见异常类型

1. FormatException

当字符串格式不正确时抛出,例如尝试将非数字字符串转换为数字。

dart
void main() {
  try {
    int.parse('abc'); // 会抛出 FormatException
  } catch (e) {
    print(e); // 输出:FormatException: Invalid radix-10 number
  }
}

2. RangeError

当访问集合的索引超出范围时抛出。

dart
void main() {
  try {
    var list = [1, 2, 3];
    print(list[5]); // 会抛出 RangeError
  } catch (e) {
    print(e); // 输出:RangeError (index): Invalid value: Not in inclusive range 0..2
  }
}

3. NoSuchMethodError

当尝试调用对象不存在的方法时抛出。

dart
void main() {
  try {
    var obj = {};
    obj.nonExistentMethod(); // 会抛出 NoSuchMethodError
  } catch (e) {
    print(e); // 输出:NoSuchMethodError: Class '_InternalLinkedHashMap<String, dynamic>' has no instance method 'nonExistentMethod'.
  }
}

4. ArgumentError

当函数接收到无效的参数时抛出。

dart
void main() {
  try {
    String.fromCharCode(-1); // 会抛出 ArgumentError
  } catch (e) {
    print(e); // 输出:ArgumentError: Invalid value: Not in inclusive range 0..1114111
  }
}

5. StateError

当对象处于无效状态时抛出。

dart
void main() {
  try {
    var list = [1, 2, 3];
    list.clear();
    list.removeLast(); // 会抛出 StateError
  } catch (e) {
    print(e); // 输出:StateError: No element
  }
}

12.3 异常捕获与处理

try-catch-finally

dart
try {
  // 执行可能出现异常的代码
} catch (e) {
  // 捕获异常并处理
} finally {
  // 无论是否出现异常,都执行的代码
}

捕获指定类型的异常

dart
try {
  // 执行可能出现异常的代码
} on FormatException catch (e) {
  // 只捕获 FormatException 类型的异常
  print('Format error: $e');
} on RangeError catch (e) {
  // 只捕获 RangeError 类型的异常
  print('Range error: $e');
} catch (e) {
  // 捕获其他类型的异常
  print('Other error: $e');
} finally {
  // 无论是否出现异常,都执行的代码
  print('Operation completed');
}

重新抛出异常

dart
try {
  // 执行可能出现异常的代码
} catch (e) {
  // 处理异常
  print('Error caught: $e');
  // 重新抛出异常
  rethrow;
} finally {
  // 无论是否出现异常,都执行的代码
  print('Operation completed');
}

12.4 自定义异常

创建自定义异常类

dart
class CustomException implements Exception {
  final String message;
  
  CustomException(this.message);
  
  @override
  String toString() => 'CustomException: $message';
}

抛出自定义异常

dart
void validateAge(int age) {
  if (age < 0) {
    throw CustomException('Age cannot be negative');
  } else if (age > 120) {
    throw CustomException('Age cannot be greater than 120');
  }
  print('Age is valid: $age');
}

void main() {
  try {
    validateAge(-5); // 会抛出 CustomException
  } catch (e) {
    print(e); // 输出:CustomException: Age cannot be negative
  }
}

12.5 实操案例

捕获程序异常,实现异常提示

dart
void main() {
  print('Welcome to the calculator app!');
  
  try {
    print('Enter first number:');
    var num1 = double.parse(stdin.readLineSync()!);
    
    print('Enter operator (+, -, *, /):');
    var operator = stdin.readLineSync()!;
    
    print('Enter second number:');
    var num2 = double.parse(stdin.readLineSync()!);
    
    double result;
    switch (operator) {
      case '+':
        result = num1 + num2;
        break;
      case '-':
        result = num1 - num2;
        break;
      case '*':
        result = num1 * num2;
        break;
      case '/':
        if (num2 == 0) {
          throw ArgumentError('Division by zero is not allowed');
        }
        result = num1 / num2;
        break;
      default:
        throw ArgumentError('Invalid operator');
    }
    
    print('Result: $result');
  } on FormatException {
    print('Error: Please enter a valid number');
  } on ArgumentError catch (e) {
    print('Error: ${e.message}');
  } catch (e) {
    print('Error: $e');
  } finally {
    print('Thank you for using the calculator app!');
  }
}

避免程序崩溃

dart
import 'dart:io';

Future<String> fetchData() async {
  try {
    var client = HttpClient();
    var request = await client.getUrl(Uri.parse('https://example.com'));
    var response = await request.close();
    
    if (response.statusCode != HttpStatus.ok) {
      throw Exception('HTTP error: ${response.statusCode}');
    }
    
    return await response.transform(utf8.decoder).join();
  } on SocketException {
    return 'Error: No internet connection';
  } on HttpException catch (e) {
    return 'Error: ${e.message}';
  } catch (e) {
    return 'Error: $e';
  } finally {
    client.close();
  }
}

void main() async {
  var result = await fetchData();
  print(result);
  // 程序会继续执行,不会崩溃
  print('Program continues...');
}

12.6 异常处理最佳实践

1. 只捕获你能处理的异常

不要捕获所有异常,只捕获你知道如何处理的异常。

2. 提供具体的错误信息

在抛出异常时,提供具体、清晰的错误信息,便于调试和用户理解。

3. 使用 finally 释放资源

在 finally 块中释放资源(如文件、网络连接等),确保资源被正确释放,无论是否出现异常。

4. 不要过度使用异常

异常应该用于处理意外情况,而不是用于控制正常的程序流程。

5. 记录异常

在捕获异常时,记录异常信息,便于后续调试和分析。

小结

  • 异常 是程序运行过程中出现的错误,它会导致程序的正常执行流程被中断。
  • 常见异常类型 包括 FormatException、RangeError、NoSuchMethodError、ArgumentError、StateError 等。
  • 异常捕获与处理 使用 try-catch-finally 语句,可以捕获指定类型的异常,也可以捕获所有异常。
  • 自定义异常 通过实现 Exception 接口来创建,可以提供更具体的错误信息。
  • 异常处理最佳实践 包括只捕获能处理的异常、提供具体的错误信息、使用 finally 释放资源、不要过度使用异常、记录异常等。

通过合理的异常处理,你可以编写更健壮、更可靠的 Dart 程序,提高用户体验。

© 2026 编程马·菜鸟教程 版权所有