Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Обработка неудач: Exception Handling в Java
Обработка неудач — это критическое мастерство в разработке на Java. Речь идёт о том, как код реагирует на ошибки, исключительные ситуации и непредвиденные события.
Типы исключений в Java
Checked Exceptions (Проверяемые исключения)
Должны быть явно обработаны или объявлены в throws:
public class FileProcessor {
public void readFile(String path) throws IOException {
FileReader reader = new FileReader(path);
reader.close();
}
}
Примеры: IOException, SQLException, ParseException
Unchecked Exceptions (Необработанные исключения)
Наследуют RuntimeException, не требуют обработки:
public class Calculator {
public int divide(int a, int b) {
return a / b; // Может выбросить ArithmeticException
}
}
Примеры: NullPointerException, ArrayIndexOutOfBoundsException, IllegalArgumentException
Обработка исключений: Try-Catch-Finally
public class BankService {
public void transfer(Account from, Account to, double amount) {
try {
if (amount <= 0) {
throw new IllegalArgumentException("Amount must be positive");
}
if (from.getBalance() < amount) {
throw new InsufficientFundsException("Not enough balance");
}
from.withdraw(amount);
to.deposit(amount);
} catch (IllegalArgumentException e) {
System.err.println("Invalid input: " + e.getMessage());
// Логируем и обрабатываем специфичную ошибку
} catch (InsufficientFundsException e) {
System.err.println("Cannot transfer: " + e.getMessage());
notifyUser("Transfer failed");
} catch (Exception e) {
System.err.println("Unexpected error: " + e);
logger.error("Transfer failed unexpectedly", e);
} finally {
// Это выполнится ВСЕ РАВНО, даже если было исключение
System.out.println("Transfer attempt completed");
closeConnection();
}
}
}
Try-With-Resources (Автоматическая очистка)
public class SafeFileReader {
public void readFile(String path) throws IOException {
// Ресурс автоматически закроется
try (FileReader reader = new FileReader(path);
BufferedReader buffered = new BufferedReader(reader)) {
String line;
while ((line = buffered.readLine()) != null) {
System.out.println(line);
}
}
// reader и buffered закроются автоматически
}
}
Преимущество: не забудешь закрыть ресурс.
Custom исключения
// Создаём своё исключение
public class InsufficientFundsException extends Exception {
private double required;
private double available;
public InsufficientFundsException(double required, double available) {
super("Required: " + required + ", Available: " + available);
this.required = required;
this.available = available;
}
public double getShortfall() {
return required - available;
}
}
Использование:
if (balance < amount) {
throw new InsufficientFundsException(amount, balance);
}
Обработка цепочек исключений
public class DataService {
public User loadUser(int id) {
try {
return database.findUser(id);
} catch (SQLException e) {
// Оборачиваем в более высокоуровневое исключение
throw new DataAccessException("Failed to load user: " + id, e);
}
}
}
Лучшие практики обработки ошибок
1. Не подавляй исключения
// ПЛОХО: проблема скрыта
try {
processData();
} catch (Exception e) {
// Молчание — золото? НЕТ!
}
// ХОРОШО: логируем и обрабатываем
try {
processData();
} catch (Exception e) {
logger.error("Processing failed", e);
throw new ProcessingException("Data processing error", e);
}
2. Специфичные catch блоки
// ПЛОХО: ловим ВСЁ
try {
operation();
} catch (Exception e) {
handle(e);
}
// ХОРОШО: ловим конкретные ошибки
try {
operation();
} catch (DatabaseException e) {
handleDatabaseError(e);
} catch (ValidationException e) {
handleValidationError(e);
} catch (RuntimeException e) {
handleUnexpectedError(e);
}
3. Валидируй входные данные рано
public void createUser(String name, String email) {
if (name == null || name.trim().isEmpty()) {
throw new IllegalArgumentException("Name cannot be empty");
}
if (!isValidEmail(email)) {
throw new IllegalArgumentException("Invalid email format");
}
// Теперь безопасно работать с данными
}
4. Используй Optional для null-safety
// ПЛОХО: NullPointerException может всплыть
User user = findUser(id);
String email = user.getEmail();
// ХОРОШО: явно обрабатываем null
Optional<User> user = findUser(id);
String email = user.map(User::getEmail).orElse("unknown@example.com");
Логирование ошибок
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class OrderService {
private static final Logger logger = LoggerFactory.getLogger(OrderService.class);
public void processOrder(Order order) {
try {
validateOrder(order);
saveOrder(order);
logger.info("Order processed successfully: {}", order.getId());
} catch (ValidationException e) {
logger.warn("Order validation failed: {}", e.getMessage());
} catch (Exception e) {
logger.error("Unexpected error processing order", e);
sendAlertToAdmin(e);
}
}
}
Ключевые выводы
- Не подавляй ошибки — логируй, обрабатывай, пробрасывай дальше если нужно
- Специфичные исключения — лучше, чем ловля Exception
- Валидируй рано — ошибки на входе лучше, чем внутри логики
- Try-with-resources — используй для автоматической очистки
- Custom исключения — делают код более читаемым
- Optional вместо null — избегай NullPointerException
- Логируй все ошибки — они помогают в отладке и мониторинге в продакшене