← Назад к вопросам

Что будет с программой, если не обрабатывать исключения?

1.0 Junior🔥 71 комментариев
#Основы Java

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что будет с программой, если не обрабатывать исключения

Это критически важный вопрос о надёжности Java приложений. Рассмотрю различные сценарии и последствия отсутствия обработки исключений.

Основной эффект: программа упадёт (crash)

Если исключение не обработано, оно распространяется вверх по стеку вызовов. Если его никто не ловит, программа завершает работу.

// ❌ БЕЗ обработки исключения
public class BankApp {
    public static void main(String[] args) {
        String amount = "invalid_number";  // Не число!
        int money = Integer.parseInt(amount);  // throws NumberFormatException
        System.out.println("Перевод: " + money);
    }
}

// Результат:
// Exception in thread "main" java.lang.NumberFormatException:
// For input string: "invalid_number"
// StackTrace показывает где упали
// ПРОГРАММА ЗАВЕРШЕНА

Иерархия обработки исключений

метод A() {
    try {
        method B();  // throws FileNotFoundException
    } catch (FileNotFoundException e) {
        // Поймали - программа продолжает работу
    }
}

метод B() {
    // NO try-catch - исключение летит в A()
    File file = new File("missing.txt");
    FileReader reader = new FileReader(file);  // throws
}

Исключение распространяется:

Exception thrown in B() 
    → не обработано в B()
    → летит в A() 
    → обработано в A() с catch
    → программа продолжает работу ✅

1. Unhandled Exception → Thread Dies

Если исключение не обработано и находится в отдельном потоке:

new Thread(() -> {
    String data = getUserInput();  // может быть null
    System.out.println(data.length());  // NullPointerException
    // Нет try-catch - поток упадёт, но основное приложение продолжит
}).start();

System.out.println("Главный поток работает");  // Выведется

Результат:

  • Поток умрёт
  • Основное приложение продолжит жить
  • Данные потока потеряются
  • Ошибка может быть незаметна

2. Main Thread → Crash Application

Если исключение в главном потоке:

public class UserService {
    public static void main(String[] args) {
        try {
            User user = findUserById(-1);  // throws IllegalArgumentException
        } catch (IllegalArgumentException e) {
            System.out.println("Ошибка: " + e.getMessage());
            // Приложение продолжит работу
        }
        
        System.out.println("Программа ещё живо");
    }
}

// А БЕЗ catch:
public class UserServiceBad {
    public static void main(String[] args) {
        User user = findUserById(-1);  // throws - не обработано
        System.out.println(user);  // Никогда не выполнится
    }
}
// ПРОГРАММА УПАДЁТ

3. Web Application: Error Response вместо Crash

В Spring Boot приложении есть встроенная обработка:

@RestController
@RequestMapping("/api/users")
public class UserController {
    // БЕЗ try-catch - Spring автоматически обработает
    @GetMapping("/{id}")
    public User getUser(@PathVariable Long id) {
        return userService.findById(id);  // может выбросить исключение
    }
}

// Если findById() выбросит исключение:
// Spring перехватит его и вернёт HTTP 500 Error
// Приложение НЕ упадёт, но клиент получит ошибку

4. Игнорирование исключения (Empty Catch)

// ❌ ОЧЕНЬ ПЛОХО - Silent failure
try {
    processPayment(order);
} catch (PaymentException e) {
    // Пусто! Ошибка скрыта
}

System.out.println("Платёж успешен!");  // Соврут пользователю!

// Последствия:
// - Деньги не переведены, но пользователь думает что всё ок
// - Баланс рассинхронизирован
// - Очень трудно найти баг в production

Лучше так:

try {
    processPayment(order);
} catch (PaymentException e) {
    logger.error("Payment failed for order {}: {}", order.getId(), e);
    throw new OrderProcessingException("Платёж не прошёл", e);
    // Или хотя бы:
    // notifyUserOfError(e);
}

5. Checked vs Unchecked Exceptions

Checked Exception — компилятор требует обработки:

// ❌ НЕ КОМПИЛИРУЕТСЯ
public void readFile() {
    FileReader reader = new FileReader("file.txt");  // throws IOException
}

// ✅ НУЖНО обработать или объявить
public void readFile() throws IOException {
    FileReader reader = new FileReader("file.txt");  // OK
}

// Или:
public void readFile() {
    try {
        FileReader reader = new FileReader("file.txt");
    } catch (IOException e) {
        logger.error("Cannot read file", e);
    }
}

Unchecked Exception — компилятор НЕ требует:

// ✅ КОМПИЛИРУЕТСЯ, но может упасть в runtime
public void process(List<User> users) {
    User user = users.get(100);  // IndexOutOfBoundsException если < 100
    System.out.println(user.getName());  // NullPointerException если null
}

6. Практический пример: Банковское приложение

// ❌ БЕЗ обработки - может упасть
public class BankTransaction {
    public void transfer(Account from, Account to, double amount) {
        from.withdraw(amount);      // Может выбросить InsufficiencyFundsException
        to.deposit(amount);          // Может выбросить AccountBlockedException
        logger.info("Transfer complete");
    }
}

// Если не обработать:
// 1. withdraw() успешен, но to.deposit() выбросит исключение
// 2. Деньги ушли из аккаунта From
// 3. Но не пришли на To
// 4. Деньги потеряны!

✅ ПРАВИЛЬНАЯ реализация:

public void transfer(Account from, Account to, double amount) 
    throws TransferException {
    
    // Проверяем предусловия
    if (amount <= 0) {
        throw new IllegalArgumentException("Amount must be positive");
    }
    
    try {
        from.withdraw(amount);
    } catch (InsufficientFundsException e) {
        throw new TransferException("Insufficient funds", e);
    }
    
    try {
        to.deposit(amount);
    } catch (AccountBlockedException e) {
        // ROLLBACK! Вернуть деньги
        from.deposit(amount);  // Это тоже может упасть!
        throw new TransferException("Recipient account blocked", e);
    }
    
    logger.info("Transfer successful: {} -> {} amount {}", 
        from.getId(), to.getId(), amount);
}

7. Последствия в production

ПроблемаРезультат
CrashПриложение недоступно, требуется перезагрузка
Data lossПотеря данных, проблемы с консистентностью
SecurityStack trace виден пользователю (информация для хакеров)
Silent failureПользователь думает что всё ok, но данные неправильные
PerformanceЕсли много исключений, создание stack trace замедляет
DebuggingОчень трудно найти реальную причину ошибки

8. Best Practices для обработки

1. Обрабатывай специфичные исключения:

try {
    user = userService.findById(id);
} catch (UserNotFoundException e) {
    return ResponseEntity.notFound().build();
} catch (DatabaseException e) {
    logger.error("DB error", e);
    return ResponseEntity.status(500).build();
}

2. Логируй с контекстом:

try {
    processOrder(orderId);
} catch (OrderProcessingException e) {
    logger.error("Failed to process order {}: {}", orderId, e.getMessage(), e);
    // Сохрани в DB для аудита
    errorService.recordError(orderId, e);
}

3. Не съедай исключения:

// ❌ ПЛОХО
try {
    // код
} catch (Exception e) {
    // Ничего не делаем, продолжаем
}

// ✅ ХОРОШО
try {
    // код
} catch (SpecificException e) {
    // Логируем и переделаем обработанное исключение
    logger.error("Error occurred", e);
    // или throw new RuntimeException(...)
}

4. Используй try-with-resources (для ресурсов):

// Автоматически закроет reader
try (FileReader reader = new FileReader("file.txt")) {
    // читаем
} catch (IOException e) {
    logger.error("IO error", e);
}

Заключение

Если не обрабатывать исключения:

  1. Синхронный код (main thread) → программа упадёт
  2. Асинхронный код (другой поток) → поток умрёт, основное приложение живет
  3. Web приложение (Spring) → вернётся HTTP 500 ошибка
  4. Silent failure → больше всего вреда (непредсказуемое состояние)

Правило: Всегда обрабатывай исключения явно, логируй их, и даже если не знаешь что делать — перебросъ дальше (throw), чтобы верхний уровень мог обработать.

Помни: исключения — это нормально, это часть контроля потока. Главное — обработай их правильно.

Что будет с программой, если не обрабатывать исключения? | PrepBro