В чем разница между ошибкой (Error) и исключением (Exception) в Java?

Ответ

В Java Error и Exception — это разные подклассы Throwable, и понимание их различий критично для написания надёжных тестов и корректной обработки сбоев.

Исключения (Exception)

  • Представляют проблемы, которые приложение может и должно обработать.
  • Являются частью бизнес-логики.
  • Две категории:
    1. Проверяемые (Checked) исключения: Наследники Exception (но не RuntimeException). Компилятор требует их обработки (блок try-catch) или объявления в сигнатуре метода (throws). Пример: IOException, SQLException. Используются для ожидаемых ошибок внешних систем.
    2. Непроверяемые (Unchecked) исключения: Наследники RuntimeException. Компилятор не требует их явной обработки. Пример: NullPointerException, IllegalArgumentException, ArrayIndexOutOfBoundsException. Часто указывают на ошибки в логике программы.

Ошибки (Error)

  • Представляют серьёзные, критические проблемы, с которыми приложение обычно не должно пытаться справиться.
  • Указывают на сбои в среде выполнения Java (JVM) или системе.
  • Примеры: OutOfMemoryError (закончилась память), StackOverflowError (бесконечная рекурсия), VirtualMachineError.
  • Обычно их не перехватывают (кроме специфических сценариев логирования/завершения работы).

Пример в тестах:

// 1. Проверяемое исключение (Checked Exception) - тестируем корректную обработку
@Test
public void testFileNotFoundHandling() {
    FileReaderService service = new FileReaderService();
    // Ожидаем, что при отсутствии файла сервис выбросит определённое исключение
    assertThrows(FileNotFoundException.class, () -> {
        service.readFile("non_existent.txt");
    });
}

// 2. Непроверяемое исключение (Unchecked Exception) - тестируем валидацию аргументов
@Test
public void testInvalidInputThrowsException() {
    Calculator calc = new Calculator();
    // Ожидаем, что передача null вызовет IllegalArgumentException
    assertThrows(IllegalArgumentException.class, () -> {
        calc.divide(10, null);
    });
}

// 3. Error - обычно НЕ тестируем специально, но должны понимать причину
// Тест, который потребляет всю память, может упасть с OutOfMemoryError,
// но это не failure теста, а проблема конфигурации среды.

Для QA: В автотестах мы чаще всего проверяем, что код бросает ожидаемые Exception (checked или unchecked) при некорректных условиях. Error же сигнализирует о проблемах в тестовом окружении.

Ответ 18+ 🔞

А, слушай, вот тема, про которую многие путаются, пока на практике не наступят. В Java есть Error и Exception, оба от Throwable растут, но это, блядь, как небо и земля. Если их не различать, потом сидишь и думаешь, почему всё накрылось медным тазом, а тесты кричат что-то невнятное.

Исключения (Exception) — это, типа, рабочие моменты Их приложение в теории может и должно пережить. Это часть бизнес-логики, ёпта.

  • Проверяемые (Checked): Наследники Exception, но не RuntimeException. Компилятор на них орет, как сука, требует либо обернуть в try-catch, либо в сигнатуре метода throws написать. Типа IOException или SQLException. Это когда внешняя система обосралась — мы это предвидели.
  • Непроверяемые (Unchecked): Это уже наследники RuntimeException. Компилятор на них похуй, не требует обязательной обработки. Это обычно наши косяки по невнимательности: NullPointerException (тыкнул в null), IllegalArgumentException (плохой аргумент передал). Если они вылезли — иди код смотри, там логика гнилая.

Ошибки (Error) — это уже пиздец, Карл Это не проблемы твоего кода, а жёсткие системные аварии. Среда выполнения (JVM) ебнулась. С ними обычно не борются, потому что нечем.

  • Примеры: OutOfMemoryError (память кончилась, ядрёна вошь), StackOverflowError (рекурсия ушла в бесконечность), VirtualMachineError.
  • Ловить их — плохая идея (разве что для красивого логирования перед смертью). Это как пытаться заклеить скотчем падающий самолёт.

Ну и в тестах это как выглядит:

// 1. Проверяемое исключение — мы его ждём и проверяем, что логика обработки работает
@Test
public void testFileNotFoundHandling() {
    FileReaderService service = new FileReaderService();
    // Ожидаем, что сервис корректно свалится с нужной ошибкой, если файла нет
    assertThrows(FileNotFoundException.class, () -> {
        service.readFile("non_existent.txt");
    });
}

// 2. Непроверяемое исключение — тестируем, что на кривые данные код не молча сдохнет, а красиво ругнётся
@Test
public void testInvalidInputThrowsException() {
    Calculator calc = new Calculator();
    // Ждём, что передача null вызовет конкретную ошибку валидации
    assertThrows(IllegalArgumentException.class, () -> {
        calc.divide(10, null);
    });
}

// 3. Error — специально их тестировать — это, бля, мудя полная.
// Если тест падает с OutOfMemoryError, это не провал теста, а пиздец в окружении.
// Беги смотреть, сколько памяти выделил или где у тебя утечка.

Для QA/автотестеров: Твоя основная работа — ловить и проверять, что код кидает правильные Exception (и checked, и unchecked) когда надо. А если в логах Error полез — это уже волнение ебать, беги смотреть, что не так с железом, памятью или настройками енвы. Доверия к таким падениям — ноль, пока не починишь среду.