← Назад к вопросам
Как компиляция программы влияет на появление исключений
2.2 Middle🔥 161 комментариев
#ООП#Основы Java
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Влияние компиляции на исключения в Java
Это важная тема, которая касается разницы между compile-time и runtime ошибками.
1. Compile-time исключения (Checked Exceptions)
Проверяются компилятором и ДОЛЖНЫ быть обработаны:
import java.io.*;
public class FileProcessor {
// Метод объявляет проверяемое исключение
public String readFile(String filename) throws IOException {
// IOException — checked exception, требует обработки
BufferedReader reader = new BufferedReader(new FileReader(filename));
String line = reader.readLine();
reader.close();
return line;
}
// Вариант 1: throws (передаём ответственность выше)
public void processFile(String filename) throws IOException {
String content = readFile(filename);
System.out.println(content);
}
// Вариант 2: try-catch (обрабатываем)
public void processFileWithHandler(String filename) {
try {
String content = readFile(filename);
System.out.println(content);
} catch (IOException e) {
System.err.println("Ошибка чтения файла: " + e.getMessage());
}
}
// Вариант 3: try-with-resources (автоматическое закрытие ресурсов)
public String readFileSafe(String filename) throws IOException {
try (BufferedReader reader = new BufferedReader(new FileReader(filename))) {
return reader.readLine();
} // reader закроется автоматически
}
}
// Если не обработать — КОД НЕ СКОМПИЛИРУЕТСЯ!
// Error: unhandled exception type IOException
2. Runtime исключения (Unchecked Exceptions)
Не проверяются компилятором, но могут возникнуть во время выполнения:
public class ArithmeticExample {
// КОМПИЛИРУЕТСЯ БЕЗ ОШИБОК
public int divide(int a, int b) {
return a / b; // ArithmeticException при b == 0
}
// КОМПИЛИРУЕТСЯ БЕЗ ОШИБОК
public void accessArray(int[] arr, int index) {
System.out.println(arr[index]); // ArrayIndexOutOfBoundsException
}
// КОМПИЛИРУЕТСЯ БЕЗ ОШИБОК
public String getString(Object obj) {
return (String) obj; // ClassCastException
}
// КОМПИЛИРУЕТСЯ БЕЗ ОШИБОК
public void nullPointer() {
String str = null;
int len = str.length(); // NullPointerException
}
// Обработка опциональна, но рекомендуется
public void safeArithmetic(int a, int b) {
try {
int result = divide(a, b);
System.out.println("Результат: " + result);
} catch (ArithmeticException e) {
System.err.println("Деление на ноль!");
}
}
}
3. Иерархия исключений
// Класс Exception — иерархия
Throwable
├── Error (fatal, не обрабатываем)
│ ├── OutOfMemoryError
│ ├── StackOverflowError
│ └── VirtualMachineError
├── Exception
│ ├── Checked (ДОЛЖНЫ быть обработаны)
│ │ ├── IOException
│ │ ├── SQLException
│ │ ├── FileNotFoundException
│ │ └── ClassNotFoundException
│ └── RuntimeException (Unchecked, опционально)
│ ├── NullPointerException
│ ├── ArrayIndexOutOfBoundsException
│ ├── ClassCastException
│ ├── IllegalArgumentException
│ └── ArithmeticException
4. Влияние на компиляцию: примеры
import java.sql.SQLException;
import java.io.IOException;
public class CompilationExample {
// ОШИБКА 1: Unchecked exception в throws — странно, но разрешено
public void method1() throws NullPointerException {
// Компилируется, но это плохая практика
String str = null;
System.out.println(str.length());
}
// ОШИБКА 2: Забыли обработать checked exception
// public void readFromDatabase() {
// Connection conn = DriverManager.getConnection("...");
// // Compilation error: unhandled exception type SQLException
// }
// ПРАВИЛЬНО: throws или try-catch
public void readFromDatabase() throws SQLException {
Connection conn = java.sql.DriverManager.getConnection("...");
// Теперь компилируется
}
// ПРАВИЛЬНО: try-catch
public void readFromDatabaseSafe() {
try {
Connection conn = java.sql.DriverManager.getConnection("...");
} catch (SQLException e) {
System.err.println("Ошибка БД: " + e.getMessage());
}
}
}
5. Custom исключения
// Checked custom exception
public class InvalidUserException extends Exception {
public InvalidUserException(String message) {
super(message);
}
public InvalidUserException(String message, Throwable cause) {
super(message, cause);
}
}
// Unchecked custom exception
public class ValidationException extends RuntimeException {
public ValidationException(String message) {
super(message);
}
}
// Использование
public class UserService {
public void registerUser(String email) throws InvalidUserException {
if (email == null || !email.contains("@")) {
throw new InvalidUserException("Invalid email: " + email);
}
}
public void validateAge(int age) {
if (age < 0) {
throw new ValidationException("Age cannot be negative");
}
}
}
6. Best Practices
public class ExceptionBestPractices {
// ❌ ПЛОХО: Поймали, но ничего не сделали
public void badHandler() {
try {
riskyOperation();
} catch (IOException e) {
// Молча проигнорировали ошибку!
}
}
// ✅ ХОРОШО: Залогировали и обработали
public void goodHandler() {
try {
riskyOperation();
} catch (IOException e) {
System.err.println("Операция не удалась: " + e.getMessage());
// Или передали дальше
throw new RuntimeException("Operation failed", e);
}
}
// ✅ ЛУЧШЕ: Переброс как более специфичное исключение
public void bestHandler() throws ApplicationException {
try {
riskyOperation();
} catch (IOException e) {
throw new ApplicationException("Failed to perform operation", e);
}
}
// ✅ ИДЕАЛЬНО: try-with-resources + конкретная обработка
public String readConfig(String path) throws ConfigException {
try (BufferedReader reader = new BufferedReader(new FileReader(path))) {
return reader.readLine();
} catch (FileNotFoundException e) {
throw new ConfigException("Config file not found: " + path);
} catch (IOException e) {
throw new ConfigException("Failed to read config", e);
}
}
private void riskyOperation() throws IOException {}
}
Главные выводы:
- Checked exceptions — проверяются ВО ВРЕМЯ компиляции, код не скомпилируется без обработки
- Unchecked exceptions — НЕ проверяются компилятором, но могут выброситься во время выполнения
- throws — передаёт ответственность в вызывающий код
- try-catch — обрабатывает исключение локально
- try-with-resources — автоматически закрывает ресурсы
Правильная обработка исключений критична для надёжного и поддерживаемого кода.