Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# Checked Исключение (Checked Exception)
Определение
Checked исключение — это исключение, которое обязательно должно быть обработано или объявлено в сигнатуре метода с помощью ключевого слова throws. Компилятор Java проверяет это и не компилирует код, если checked исключение не обработано. Checked исключение наследуется от класса Exception (но НЕ от RuntimeException).
Основное назначение
1. Различие между Checked и Unchecked исключениями
// CHECKED исключение (наследуется от Exception напрямую)
public class FileNotFoundException extends IOException { }
public class SQLException extends Exception { }
// Компилятор ТРЕБУЕТ обработку или throws
public void readFile(String path) throws FileNotFoundException {
// Обязательно указать throws
FileReader reader = new FileReader(path); // Throws FileNotFoundException
}
// UNCHECKED исключение (наследуется от RuntimeException)
public class NullPointerException extends RuntimeException { }
// Компилятор НЕ требует обработку
public void printLength(String str) {
System.out.println(str.length()); // Может выбросить NPE, но это OK
}
2. Когда выбрасываются Checked исключения
Операции с файлами:
// IOException и FileNotFoundException — checked
public String readFile(String path) throws IOException {
FileReader reader = new FileReader(path); // Throws FileNotFoundException
BufferedReader buffered = new BufferedReader(reader);
String content = buffered.readLine(); // Throws IOException
reader.close(); // Throws IOException
return content;
}
// Использование
try {
String content = readFile("config.txt");
} catch (FileNotFoundException e) {
System.out.println("File not found: " + e.getMessage());
} catch (IOException e) {
System.out.println("Error reading file: " + e.getMessage());
}
Операции с БД:
// SQLException — checked
public List<User> getAllUsers() throws SQLException {
Connection conn = getConnection(); // Throws SQLException
Statement stmt = conn.createStatement(); // Throws SQLException
ResultSet rs = stmt.executeQuery("SELECT * FROM users"); // Throws SQLException
return mapToUsers(rs);
}
// Использование
try {
List<User> users = getAllUsers();
} catch (SQLException e) {
System.out.println("Database error: " + e.getMessage());
// Логирование, откат транзакции и т.д.
}
Сетевые операции:
// IOException — checked
public String fetchData(String url) throws IOException {
URL urlObj = new URL(url);
HttpURLConnection conn = (HttpURLConnection) urlObj.openConnection(); // IOException
BufferedReader reader = new BufferedReader(
new InputStreamReader(conn.getInputStream()) // IOException
);
String line = reader.readLine(); // IOException
return line;
}
// Использование
try {
String data = fetchData("https://api.example.com/data");
} catch (IOException e) {
System.out.println("Network error: " + e.getMessage());
// Повтор запроса или использование fallback
}
3. Принцип работы Checked исключений
// Метод должен либо обработать, либо объявить throws
public void processData(String filename) {
try {
readFile(filename); // IOException — checked
} catch (IOException e) {
System.out.println("Обработка ошибки");
}
// ИЛИ
}
public void processData(String filename) throws IOException {
readFile(filename); // IOException — checked, но объявлена в throws
}
public void readFile(String filename) throws IOException {
FileReader reader = new FileReader(filename);
}
4. Распространение Checked исключений
// Если не обработать, то ОБЯЗАТЕЛЬНО объявить throws
public void method1() throws IOException {
method2(); // IOException распространяется
}
public void method2() throws IOException {
method3(); // IOException распространяется
}
public void method3() throws IOException {
readFile("data.txt"); // IOException выбрасывается здесь
}
// Вызов
try {
method1();
} catch (IOException e) {
System.out.println("Error in chain: " + e.getMessage());
}
5. Обработка множественных Checked исключений
public class DataProcessor {
public void process(String filepath) throws IOException, SQLException {
String data = readFile(filepath); // Throws IOException
List<User> users = parseUsers(data);
saveToDatabase(users); // Throws SQLException
}
private String readFile(String path) throws IOException {
FileReader reader = new FileReader(path);
// ...
return content;
}
private void saveToDatabase(List<User> users) throws SQLException {
Connection conn = getConnection();
// ...
}
}
// Использование
try {
processor.process("users.csv");
} catch (IOException e) {
System.out.println("File error: " + e.getMessage());
} catch (SQLException e) {
System.out.println("Database error: " + e.getMessage());
}
6. Создание собственного Checked исключения
// Наследуем от Exception (НЕ от RuntimeException!)
public class InvalidCredentialsException extends Exception {
public InvalidCredentialsException(String message) {
super(message);
}
public InvalidCredentialsException(String message, Throwable cause) {
super(message, cause);
}
}
public class AuthService {
public User login(String email, String password)
throws InvalidCredentialsException {
User user = findByEmail(email);
if (user == null) {
throw new InvalidCredentialsException(
"User not found: " + email
);
}
if (!user.getPassword().equals(hashPassword(password))) {
throw new InvalidCredentialsException(
"Invalid password for user: " + email
);
}
return user;
}
}
// Использование
try {
User user = authService.login("john@example.com", "password123");
System.out.println("Login successful: " + user.getName());
} catch (InvalidCredentialsException e) {
System.out.println("Login failed: " + e.getMessage());
}
7. Примеры встроенных Checked исключений
// IOException и подклассы
throws FileNotFoundException; // Файл не найден
throws SocketException; // Проблема с сокетом
throws EOFException; // Конец файла
// SQLException
throws SQLException; // Ошибка БД
// Reflection
throws ClassNotFoundException; // Класс не найден
throws NoSuchMethodException; // Метод не найден
// Java Naming and Directory Interface
throws NamingException; // JNDI ошибка
// JSON
throws ParseException; // Ошибка парсинга
8. Try-with-resources для Checked исключений
// Старый подход (много кода)
public String readFile(String path) throws IOException {
FileReader reader = null;
try {
reader = new FileReader(path);
return reader.readLine();
} finally {
if (reader != null) {
reader.close(); // Throws IOException
}
}
}
// Новый подход (Java 7+) — автоматическое закрытие ресурсов
public String readFile(String path) throws IOException {
try (FileReader reader = new FileReader(path); // Throws IOException
BufferedReader buffered = new BufferedReader(reader)) {
return buffered.readLine();
}
// reader и buffered автоматически закрыты
}
9. Обёртывание Checked в Unchecked (AntiPattern)
// ПЛОХО — скрывать checked исключение в unchecked
public String readFile(String path) {
try {
FileReader reader = new FileReader(path);
return reader.readLine();
} catch (IOException e) {
throw new RuntimeException(e); // Плохая практика!
}
}
// ХОРОШО — явно объявить throws
public String readFile(String path) throws IOException {
FileReader reader = new FileReader(path);
return reader.readLine();
}
// Если нужно обернуть:
public String readFile(String path) throws DataAccessException {
try {
FileReader reader = new FileReader(path);
return reader.readLine();
} catch (IOException e) {
throw new DataAccessException("Failed to read file: " + path, e);
}
}
10. Сравнение Checked vs Unchecked (повторение)
| Параметр | Checked | Unchecked |
|---|---|---|
| Наследник | Exception | RuntimeException |
| Проверка компилятором | Да (обязательно) | Нет |
| throws в сигнатуре | Обязателен | Не требуется |
| try-catch | Обязателен | Опционален |
| Использование | Ошибки окружения | Ошибки программиста |
| Примеры | IOException, SQLException | NPE, IndexOutOfBoundsException |
| Когда выбрасывается | I/O, БД, сеть | Ошибки логики |
Выводы
Checked исключение нужно для:
- Обозначения ошибок окружения, которые нельзя предотвратить (файл удалён, сеть упала)
- Принуждения программиста к обработке возможных ошибок
- Сигнализирования о том, что метод может выбросить исключение
- Разделения ответственности между разработчиком и окружением
Это фундаментальный механизм Java для обработки ошибок, обеспечивающий надёжность приложений через compile-time безопасность. Хорошее приложение правильно использует checked исключения для I/O и external системы.