Appearance
第12章:Dart 异常处理(实战必备)
12.1 异常的概念
异常是程序运行过程中出现的错误,它会导致程序的正常执行流程被中断。在 Dart 中,异常是一个对象,通常是 Exception 或 Error 的子类。
异常处理的目的是:
- 捕获并处理异常,避免程序崩溃
- 提供友好的错误提示
- 保证程序的健壮性和可靠性
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 程序,提高用户体验。
