Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Разница между Error и Exception в Dart/Flutter
В Dart существует ясное различие между Error и Exception. Хотя оба наследуются от Throwable, они используются для разных ситуаций и имеют разные предназначения.
Exception — ожидаемые ошибки
Exception — это исключение, которое может произойти во время выполнения программы и которое разумно обрабатывать. Это программные ошибки, которые предусмотрены и должны быть обработаны.
// Встроенные типы Exception
try {
int result = 10 ~/ 0; // IntegerDivisionByZeroException
} on IntegerDivisionByZeroException {
print("Cannot divide by zero");
}
try {
List<int> list = [1, 2, 3];
print(list[10]); // RangeError
} on RangeError catch (e) {
print("Index out of bounds: $e");
}
// Custom Exception
class UserNotFoundException implements Exception {
final String message;
UserNotFoundException(this.message);
@override
String toString() => "User not found: $message";
}
Future<User> fetchUser(String id) async {
final response = await http.get(Uri.parse("/api/users/$id"));
if (response.statusCode == 404) {
throw UserNotFoundException(id);
}
return User.fromJson(json.decode(response.body));
}
// Использование
try {
final user = await fetchUser("123");
} on UserNotFoundException catch (e) {
print("Error: $e");
} on SocketException catch (e) {
print("Network error: $e");
} catch (e) {
print("Unknown error: $e");
}
Error — непредвиденные критические ошибки
Error — это неисправимая ошибка, которая указывает на серьёзную проблему в коде или окружении. Errors НЕ должны обрабатываться, так как они указывают на проблему, которую нужно исправить в коде.
// Встроенные типы Error
// StackOverflowError — бесконечная рекурсия
int recursion(int n) {
return recursion(n + 1); // StackOverflowError
}
// OutOfMemoryError — закончилась память
final hugeList = List<int>.generate(999999999999, (i) => i); // OutOfMemoryError
// NoSuchMethodError — метод не существует
class MyClass {}
MyClass obj = MyClass();
obj.nonExistentMethod(); // NoSuchMethodError
// AssertionError — assertion не выполнился
class User {
final String email;
User(this.email) {
assert(email.contains('@'), 'Invalid email format');
}
}
// TypeError — неправильный тип (выявляется в runtime в некоторых случаях)
dynamic value = "string";
int result = value as int; // CastError (подтип TypeError)
Главные различия
| Аспект | Exception | Error |
|---|---|---|
| Предназначение | Обработка ошибок приложения | Критические сбои |
| Ожидаемость | Ожидаемое, может произойти | Непредвиденное, не должно |
| Обработка | Должна обрабатываться | Не должна обрабатываться |
| Примеры | FileNotFound, NetworkError | StackOverflow, OutOfMemory |
| Наследование | Реализует Exception | Наследует Error |
| catch() | Можно ловить | Нежелательно ловить |
Структура иерархии
Object
└─ Throwable
├─ Exception (Ловим и обрабатываем)
│ ├─ ArgumentError
│ ├─ FormatException
│ ├─ StateError
│ └─ Custom exceptions (UserNotFoundException и т.д.)
│
└─ Error (Не ловим)
├─ AssertionError
├─ TypeError
├─ NoSuchMethodError
├─ StackOverflowError
└─ OutOfMemoryError
Практические примеры во Flutter
Правильная обработка Exception:
Future<void> loadUserData() async {
try {
final userId = await getUserIdFromSharedPrefs();
final user = await fetchUser(userId);
setState(() => _user = user);
} on SocketException {
_showSnackBar("Network error. Check your connection");
} on TimeoutException {
_showSnackBar("Request timed out. Try again");
} on UserNotFoundException {
_showSnackBar("User not found");
} catch (e) {
_showSnackBar("Unknown error: $e");
}
}
Плохая практика — обработка Error:
// ❌ Не делай так!
try {
myFunction();
} catch (e) {
print("Error: $e"); // Может поймать Error, что скрывает проблему
}
// ❌ И уж совсем плохо — обработка всего подряд
try {
myFunction();
} catch (e) {
// Это скроет реальные проблемы в коде
}
Правильная практика:
// ✅ Ловим только Exception
try {
myFunction();
} on TimeoutException catch (e) {
// Обрабатываем ожидаемую ошибку
} on Exception catch (e) {
// Обрабатываем другие исключения
} catch (e, stackTrace) {
// Если всё же что-то неожиданное, логируем для debug
debugPrintStack(label: "Unexpected error: $e", stackTrace: stackTrace);
rethrow; // Пробрасываем выше
}
Custom Exception vs Error
Создавай Custom Exception для ожидаемых ошибок:
// ✅ Exception для логики приложения
class InvalidCredentialsException implements Exception {
final String message;
InvalidCredentialsException(this.message);
@override
String toString() => message;
}
// Использование
try {
final user = await login(email, password);
} on InvalidCredentialsException catch (e) {
showDialog(context: context, message: e.toString());
}
Errors — это признак проблемы в коде:
// ❌ Error указывает на ошибку программиста
class User {
User(String name) {
if (name.isEmpty) {
throw AssertionError("Name cannot be empty");
}
}
}
// ✅ Используй Exception для проверки при компиляции
class User {
User(String name) {
if (name.isEmpty) {
throw ArgumentError("Name cannot be empty");
}
}
}
Заключение
- Exception — обрабатывай: сетевые ошибки, валидация, состояние приложения
- Error — не обрабатывай: указывает на ошибку в коде, которую нужно исправить
- Всегда будь специфичным в catch блоках, не ловись всё подряд
- Используй Custom Exception для явного описания ошибок твоего приложения