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

Что значит обработать исключение?

2.4 Senior🔥 81 комментариев
#Docker, Kubernetes и DevOps

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

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

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

Обработка исключений в Java

Обработать исключение — это значит перехватить (catch) исключение и принять меры, чтобы программа не завершилась аварийно. Это один из ключевых механизмов обработки ошибок в Java.

Что происходит при исключении

Когда в коде возникает ошибка (например, деление на ноль):

int x = 10 / 0;  // ArithmeticException

Java автоматически создает объект исключения и выбрасывает его вверх по стеку вызовов (call stack). Если на пути никто не перехватит это исключение, программа аварийно завершится.

Способы обработки

1. Try-Catch блок (основной способ)

Перехватываем исключение и обрабатываем его:

try {
    int result = 10 / 0;  // Потенциально опасный код
    System.out.println("Результат: " + result);
} catch (ArithmeticException e) {
    // Обработка ошибки
    System.out.println("Ошибка: деление на ноль");
    System.out.println("Детали: " + e.getMessage());
    // Логируем ошибку, уведомляем пользователя, берем default значение
}

Этот код не завершится аварийно. Программа продолжит работу.

2. Множественные catch блоки

Для разных типов ошибок разные обработчики:

try {
    String[] names = {"Alice", "Bob"};
    int age = Integer.parseInt("abc");  // NumberFormatException
    String name = names[5];  // ArrayIndexOutOfBoundsException
} catch (NumberFormatException e) {
    System.out.println("Ошибка парсинга числа: " + e.getMessage());
} catch (ArrayIndexOutOfBoundsException e) {
    System.out.println("Индекс массива не найден");
} catch (Exception e) {
    // Ловит все остальные исключения
    System.out.println("Неожиданная ошибка");
}

3. Finally блок

Код, который выполнится в любом случае (есть исключение или нет):

try {
    FileInputStream file = new FileInputStream("data.txt");
    // Читаем файл
} catch (FileNotFoundException e) {
    System.out.println("Файл не найден");
} finally {
    System.out.println("Это выполнится в любом случае");
    // Закрытие ресурсов
}

Зачем finally? Для гарантированной очистки ресурсов (закрытие файла, соединения с БД, etc.)

4. Try-with-resources (Java 7+)

Модернизированный способ работы с ресурсами:

try (FileInputStream file = new FileInputStream("data.txt")) {
    byte[] data = file.readAllBytes();
    System.out.println("Прочитано " + data.length + " байт");
} catch (IOException e) {
    System.out.println("Ошибка при чтении файла: " + e.getMessage());
}
// Ресурс автоматически закроется, even if исключение

Это чище и безопаснее, чем try-finally.

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

Throwable
├── Error (не ловим — критичные ошибки JVM)
├── Exception (ловим — обрабатываемые ошибки)
│   ├── Checked Exception (IOException, SQLException)
│   └── Unchecked Exception (RuntimeException)
│       ├── NullPointerException
│       ├── ArithmeticException
│       ├── ArrayIndexOutOfBoundsException
│       └── ...

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

public void readFile() throws IOException {  // Объявляем в сигнатуре
    FileInputStream file = new FileInputStream("data.txt");
}

Unchecked исключения — необязательны (но хорошо бы):

public void process(String data) {
    int value = Integer.parseInt(data);  // NumberFormatException не объявляется
}

Правильная обработка исключений

❌ Плохо: игнорируем исключение

try {
    int result = 10 / 0;
} catch (Exception e) {
    // Ничего не делаем — "ловушка" ошибки
}

❌ Плохо: выводим в System.out

try {
    int result = 10 / 0;
} catch (Exception e) {
    System.out.println("Ошибка");  // Теряется информация
}

✅ Хорошо: логируем и обрабатываем

try {
    int result = 10 / 0;
} catch (ArithmeticException e) {
    logger.error("Ошибка при вычислении", e);  // Логируем с полной информацией
    throw new BusinessException("Невозможно выполнить операцию", e);  // Пробрасываем дальше
}

Пробрасывание исключений (throw)

Передаем ответственность за обработку выше по цепочке:

public void saveUser(User user) throws ValidationException {
    if (user.getName() == null) {
        throw new ValidationException("Имя пользователя не может быть пусто");
    }
    // Сохраняем пользователя
}

// В другом месте
try {
    saveUser(user);
} catch (ValidationException e) {
    System.out.println("Ошибка валидации: " + e.getMessage());
}

Практический пример: обработка в микросервисе

@Service
public class UserService {
    private static final Logger logger = LoggerFactory.getLogger(UserService.class);
    private final UserRepository userRepository;
    
    public UserDTO getUserById(Long id) {
        try {
            User user = userRepository.findById(id)
                .orElseThrow(() -> new EntityNotFoundException("Пользователь не найден"));
            return mapToDTO(user);
        } catch (EntityNotFoundException e) {
            logger.warn("User not found with id: {}", id);
            throw e;  // Пробрасываем дальше для обработки в контроллере
        } catch (Exception e) {
            logger.error("Unexpected error while fetching user", e);
            throw new InternalServerException("Ошибка при получении пользователя");
        }
    }
}

@RestController
@RequestMapping("/api/v1/users")
public class UserController {
    private final UserService userService;
    
    @GetMapping("/{id}")
    public ResponseEntity<UserDTO> getUser(@PathVariable Long id) {
        try {
            return ResponseEntity.ok(userService.getUserById(id));
        } catch (EntityNotFoundException e) {
            return ResponseEntity.notFound().build();
        } catch (InternalServerException e) {
            return ResponseEntity.status(500).build();
        }
    }
}

Принципы обработки исключений

  1. Обрабатывай там, где можешь действовать — не ловишь везде, только где имеет смысл
  2. Логируй со всеми деталями — message, stack trace, контекст
  3. Не игнорируй — пустые catch блоки это зло
  4. Специфичность — ловишь конкретные исключения, не просто Exception
  5. Чистка ресурсов — используй try-with-resources или finally
  6. Custom исключения — для бизнес-логики создавай свои

Завершение

Обработать исключение — это перехватить его в try-catch и принять меры: залогировать, уведомить пользователя, использовать значение по умолчанию, пробросить дальше. Правильная обработка делает программу надежной и предсказуемой.