В чем разница между Error и Exception в Dart?

«В чем разница между Error и Exception в Dart?» — вопрос из категории Dart Core, который задают на 36% собеседований Flutter Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В Dart и Error, и Exception представляют собой объекты, которые могут быть "выброшены" (throw), но они несут разную семантическую нагрузку, следуя соглашениям языка.

  • Exception — предназначен для ожидаемых проблем в логике работы программы, которые разработчик должен предусмотреть и обработать. Это сбои в бизнес-логике, вводе данных, сетевых запросах.

    • Примеры: FormatException, TimeoutException, SocketException.
    • Создавайте свои исключения, наследуясь от Exception.
      
      class ValidationException implements Exception {
      final String message;
      ValidationException(this.message);
      @override
      String toString() => 'ValidationException: $message';
      }

    // Использование void processEmail(String email) { if (!email.contains('@')) { throw ValidationException('Invalid email format'); } // ... }

  • Error — представляет критические сбои в самой программе или виртуальной машине, которые обычно указывают на ошибку в коде или невосстановимые состояния среды выполнения. Их, как правило, не следует ловить.

    • Примеры: OutOfMemoryError, StackOverflowError, NoSuchMethodError.
    • Создавать собственные классы Error стоит только для обозначения действительно фатальных условий в программе или библиотеке.

Обработка на практике:

try {
  var data = await fetchDataFromNetwork();
  var number = int.parse(data['value']); // Может выбросить FormatException
} on SocketException catch (e) {
  // Обрабатываем конкретное исключение (нет сети)
  showOfflineSnackBar();
} on FormatException catch (e) {
  // Обрабатываем другое конкретное исключение
  log('Data format error: $e');
} catch (e, s) {
  // Универсальный catch для всего остального (включая Error, что нежелательно)
  log('Unexpected error: $enStack: $s', level: Level.error);
  rethrow; // Часто лучше дать упасть и залогировать на верхнем уровне
} finally {
  // Код, который выполнится в любом случае (например, закрытие ресурсов)
  cleanup();
}

Основное правило: ловите и обрабатывайте Exception, а Error позволяйте всплывать, чтобы они были залогированы и исправлены на этапе разработки.