← Назад к вопросам
В чем разница между RuntimeException и Exception?
1.0 Junior🔥 241 комментариев
#ООП#Основы Java
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# RuntimeException vs Exception: ключевые различия
Это одно из самых важных различий в Java. Выбор между ними влияет на дизайн всего приложения.
Иерархия
Throwable
├── Exception
│ ├── RuntimeException
│ │ ├── NullPointerException
│ │ ├── ArithmeticException
│ │ ├── IndexOutOfBoundsException
│ │ └── ...
│ └── Checked Exception
│ ├── IOException
│ ├── SQLException
│ ├── ClassNotFoundException
│ └── ...
└── Error
├── OutOfMemoryError
├── StackOverflowError
└── ...
Ключевые различия
| Аспект | RuntimeException | Exception (Checked) |
|---|---|---|
| Проверка | compile-time | Compile-time |
| Обработка | Опциональна | ОБЯЗАТЕЛЬНА |
| Когда выбросить | Programming error | Expected error |
| Примеры | NPE, IndexOOB | IOException, SQLException |
| Catch блок | Опционально | ОБЯЗАТЕЛЬНО |
RuntimeException (Unchecked)
Назначение
Oшибка программиста, которую нельзя предусмотреть
Направо ошибок, которые можно избежать кодом
Примеры
// NullPointerException (самая частая)
String str = null;
str.toUpperCase(); // RuntimeException: NullPointerException
// ArithmeticException
int result = 10 / 0; // RuntimeException: ArithmeticException
// ArrayIndexOutOfBoundsException
int[] arr = new int[5];
int val = arr[10]; // RuntimeException: ArrayIndexOutOfBoundsException
// ClassCastException
Object obj = "String";
Integer num = (Integer) obj; // RuntimeException: ClassCastException
Код БЕЗ try-catch (работает)
public int divide(int a, int b) {
return a / b; // Может выбросить ArithmeticException
// НО компилятор НЕ требует try-catch
}
public void doSomething() {
divide(10, 0); // Даже без try-catch
}
Как правильно: защита кодом
public int divide(int a, int b) {
if (b == 0) {
throw new IllegalArgumentException("b cannot be zero");
}
return a / b;
}
// ИЛИ проверка перед вызовом
public void doSomething() {
int result;
if (divisor != 0) {
result = divide(10, divisor);
}
}
Exception (Checked)
Назначение
Ожидаемая ошибка, которую можно предусмотреть
Например: файл не существует, network недоступна, БД down
Примеры
// IOException
public void readFile(String path) throws IOException {
FileInputStream fis = new FileInputStream(path);
// Файла может не быть → IOException
}
// SQLException
public void queryDatabase() throws SQLException {
Connection conn = DriverManager.getConnection(url);
// БД может быть недоступна → SQLException
}
// ClassNotFoundException
public void loadClass() throws ClassNotFoundException {
Class.forName("com.example.NonExistent");
// Класса может не быть → ClassNotFoundException
}
Код ТРЕБУЕТ try-catch (не скомпилируется без него)
// ❌ ОШИБКА КОМПИЛЯЦИИ
public void readFile(String path) {
FileInputStream fis = new FileInputStream(path);
// Unhandled exception: FileNotFoundException
}
// ✅ ПРАВИЛЬНО: throws или try-catch
public void readFile(String path) throws IOException {
FileInputStream fis = new FileInputStream(path);
}
// ИЛИ
public void readFile(String path) {
try {
FileInputStream fis = new FileInputStream(path);
} catch (IOException e) {
e.printStackTrace();
}
}
Сравнение в коде
Пример 1: Разделение нулл
// RuntimeException — защищаются кодом
public String getName(User user) {
if (user == null) { // Проверка перед использованием
throw new IllegalArgumentException("User cannot be null");
}
return user.getName();
}
// Exception — обработка в try-catch
public String readConfig(String filename) throws IOException {
try {
return Files.readString(Paths.get(filename));
} catch (IOException e) {
logger.error("Failed to read config", e);
throw e; // Пробрасываем дальше
}
}
Пример 2: Выбор между ними
// ОШИБКА: используется Checked Exception, где нужна RuntimeException
public int parseNumber(String str) throws NumberFormatException {
// NumberFormatException — это RuntimeException
// throws не нужен, но это плохой стиль
return Integer.parseInt(str);
}
// ПРАВИЛЬНО: без throws
public int parseNumber(String str) {
try {
return Integer.parseInt(str);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid number", e);
}
}
// ИЛИ просто отправляем вверх (RuntimeException)
public int parseNumber(String str) {
return Integer.parseInt(str); // Может выбросить NPE
}
Когда выбросить что
Выбрось RuntimeException, если
✅ Это ошибка программиста (logic error)
✅ Можно избежать checks в коде
✅ Это неожиданно и обработать нельзя
✅ Пример: NullPointerException, IndexOutOfBoundsException
Выбрось Checked Exception (extends Exception), если
✅ Это ожидаемая ошибка
✅ Вызывающий должен её обработать
✅ Её нельзя избежать checks
✅ Пример: IOException, SQLException
Практические примеры
Сценарий 1: Пользовательский ввод
// ❌ НЕПРАВИЛЬНО: RuntimeException для ожидаемой ошибки
public void processAge(String ageStr) {
if (Integer.parseInt(ageStr) < 0) {
throw new RuntimeException("Age cannot be negative");
}
}
// ✅ ПРАВИЛЬНО: Checked Exception
public void processAge(String ageStr) throws InvalidAgeException {
int age = Integer.parseInt(ageStr);
if (age < 0) {
throw new InvalidAgeException("Age cannot be negative");
}
}
// Вызывающий ДОЛЖЕН обработать
try {
processAge(userInput);
} catch (InvalidAgeException e) {
System.out.println("Invalid input: " + e.getMessage());
}
Сценарий 2: Работа с файлами
// IOException — Checked Exception (обязательно обработать)
public void copyFile(String source, String dest) throws IOException {
Files.copy(Paths.get(source), Paths.get(dest));
// IOException — ожидаемая ошибка (файла может не быть)
}
// Обработка
try {
copyFile("input.txt", "output.txt");
} catch (IOException e) {
logger.error("Failed to copy file", e);
}
Сценарий 3: Бизнес-логика
// ❌ ПЛОХО: Checked Exception для внутренней ошибки
public void updateUser(User user) throws InternalException {
if (user.getId() == null) {
throw new InternalException("User ID is null");
}
}
// ✅ ХОРОШО: RuntimeException для internal bugs
public void updateUser(User user) {
if (user.getId() == null) {
throw new IllegalStateException("User ID is null");
}
}
Кастомные исключения
RuntimeException
public class InvalidConfigException extends RuntimeException {
public InvalidConfigException(String message) {
super(message);
}
public InvalidConfigException(String message, Throwable cause) {
super(message, cause);
}
}
// Использование — БЕЗ throws
public String getConfig(String key) {
if (config.get(key) == null) {
throw new InvalidConfigException("Missing config: " + key);
}
return config.get(key);
}
Checked Exception
public class DatabaseException extends Exception {
public DatabaseException(String message) {
super(message);
}
public DatabaseException(String message, Throwable cause) {
super(message, cause);
}
}
// Использование — С throws
public User getUser(Long id) throws DatabaseException {
try {
return repository.findById(id);
} catch (SQLException e) {
throw new DatabaseException("Failed to get user: " + id, e);
}
}
Java 8+ и Checked Exception
Функциональное программирование вынуждает использовать Unchecked
// ❌ Functional interface не может выбросить Checked Exception
list.forEach(item -> readFile(item)); // Ошибка, если readFile throws IOException
// ✅ Обёртываем в RuntimeException
list.forEach(item -> {
try {
readFile(item);
} catch (IOException e) {
throw new UncheckedIOException(e); // RuntimeException
}
});
// ИЛИ используем утилиту
list.forEach(unchecked(this::readFile));
Мой совет
Java 8-
✅ Использовать Checked Exception для внешних ошибок (IO, DB)
✅ Использовать RuntimeException для программиста ошибок
✅ Это контракт между классом и вызывающим
Java 8+
✅ Все ещё используй Checked Exception для expected errors
❌ НО функциональное программирование делает это сложным
✅ Альтернатива: использовать Optional<T> или Result<T>
Итог
RuntimeException (Unchecked):
- Ошибка программиста
- Не требует обработки (compile не требует)
- Примеры: NPE, ArithmeticException, IndexOutOfBoundsException
Exception (Checked):
- Ожидаемая ошибка
- ТРЕБУЕТ try-catch или throws
- Примеры: IOException, SQLException
Правило: если вызывающий ДОЛЖЕН обработать → Checked Exception
если это bug → RuntimeException