Разрешено ли в Java бросать исключения типа Throwable?

«Разрешено ли в Java бросать исключения типа Throwable?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Технически — да, но делать этого не рекомендуется.

Почему можно? Ключевое слово throw в Java ожидает объект, наследующий от класса Throwable. Поскольку Throwable является корневым классом всей иерархии исключений, его можно использовать.

// Скомпилируется и выполнится
public void badPractice() throws Throwable {
    throw new Throwable("Это Throwable");
}

Почему не нужно?

  1. Нарушение семантики: Throwable имеет двух прямых наследников:
    • Error — для критических, невосстанавливаемых ошибок JVM (например, OutOfMemoryError). Их ловить обычно не следует.
    • Exception — для исключительных ситуаций, которые программа может обработать. Бросая Throwable, вы смешиваете эти принципиально разные категории.
  2. Избыточность и плохой стиль: Обработка Throwable в catch-блоке заставит перехватывать и Error, что почти всегда неверно.
  3. Best Practice: Всегда используйте максимально конкретные типы исключений.
    • Для проверяемых исключений — наследники Exception (например, IOException, SQLException).
    • Для непроверяемых (runtime) исключений — наследники RuntimeException (например, IllegalArgumentException, NullPointerException).

Правильный подход:

// Вместо Throwable используйте конкретное исключение
public void processFile(String path) throws IOException {
    if (path == null) {
        // Непроверяемое исключение
        throw new IllegalArgumentException("Path cannot be null");
    }
    // ... код, который может выбросить IOException
}