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

Всегда ли будет происходить ошибка компиляции при отсутствии обработки исключений, если в вызываемом методе используется throws?

2.3 Middle🔥 111 комментариев
#Основы Java

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

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

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

# Будет ли ошибка компиляции при отсутствии обработки throws?

Краткий ответ

НЕ всегда. Ошибка компиляции зависит от типа исключения:

  • Checked исключения (extends Exception, но не RuntimeException) → ВСЕГДА требуют обработки
  • Unchecked исключения (extends RuntimeException) → НЕ требуют обработки

Два типа исключений в Java

1. Checked Exceptions (Проверяемые исключения)

Checked исключения - это исключения, которые наследуются от Exception (но не от RuntimeException). Java ТРЕБУЕТ их обработку на уровне компиляции.

// Checked исключение
public class CustomCheckedException extends Exception {
    public CustomCheckedException(String message) {
        super(message);
    }
}

// Метод, который выбрасывает checked исключение
public void readFile(String path) throws IOException {
    FileReader reader = new FileReader(path);
    // ...
}

// ❌ ОШИБКА КОМПИЛЯЦИИ - нужна обработка
public void processFile() {
    readFile("file.txt"); // Компилятор выдаст ошибку
}

Компилятор требует:

// ✅ Способ 1: Обработка try-catch
public void processFile() {
    try {
        readFile("file.txt");
    } catch (IOException e) {
        e.printStackTrace();
    }
}

// ✅ Способ 2: Пробросить исключение (throws)
public void processFile() throws IOException {
    readFile("file.txt"); // Теперь компилируется
}

Примеры Checked исключений:

java.io.IOException
java.io.FileNotFoundException
java.sql.SQLException
java.net.MalformedURLException
java.text.ParseException
java.lang.InterruptedException
java.lang.ClassNotFoundException
java.lang.CloneNotSupportedException

2. Unchecked Exceptions (Непроверяемые исключения)

Unchecked исключения - это исключения, которые наследуются от RuntimeException. Java НЕ требует их обработку. Они могут выбрасываться в любой момент.

// Unchecked исключение
public class CustomUncheckedException extends RuntimeException {
    public CustomUncheckedException(String message) {
        super(message);
    }
}

// Метод, который выбрасывает unchecked исключение
public void divide(int a, int b) throws ArithmeticException {
    if (b == 0) {
        throw new ArithmeticException("Division by zero");
    }
    System.out.println(a / b);
}

// ✅ Ошибки компиляции НЕТ - обработка опциональна
public void calculate() {
    divide(10, 2); // Компилируется успешно
}

// ✅ Можно обработать, но не обязательно
public void calculateWithHandling() {
    try {
        divide(10, 0);
    } catch (ArithmeticException e) {
        System.out.println("Error: " + e.getMessage());
    }
}

Примеры Unchecked исключений:

java.lang.RuntimeException
java.lang.NullPointerException
java.lang.ArithmeticException
java.lang.ClassCastException
java.lang.ArrayIndexOutOfBoundsException
java.lang.IllegalArgumentException
java.lang.IllegalStateException
java.util.NoSuchElementException

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

java.lang.Throwable
├── Error (не обрабатываем)
│   ├── OutOfMemoryError
│   ├── StackOverflowError
│   └── VirtualMachineError
├── Exception (базовый класс для всех исключений)
│   ├── Checked Exception (требуют обработки!)
│   │   ├── IOException
│   │   ├── SQLException
│   │   ├── ClassNotFoundException
│   │   └── ...
│   └── RuntimeException (не требуют обработки!)
│       ├── NullPointerException
│       ├── ArithmeticException
│       ├── ClassCastException
│       ├── IllegalArgumentException
│       └── ...

Практические примеры

Пример 1: Checked исключение IOException

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

// ❌ ОШИБКА КОМПИЛЯЦИИ
public void readFileWrong() {
    String content = Files.readString(Paths.get("file.txt"));
    System.out.println(content);
    // Ошибка: IOException должно быть обработано
}

// ✅ Правильно - способ 1 (try-catch)
public void readFileWithTryCatch() {
    try {
        String content = Files.readString(Paths.get("file.txt"));
        System.out.println(content);
    } catch (IOException e) {
        System.err.println("Failed to read file: " + e.getMessage());
    }
}

// ✅ Правильно - способ 2 (throws)
public void readFileWithThrows() throws IOException {
    String content = Files.readString(Paths.get("file.txt"));
    System.out.println(content);
}

Пример 2: Unchecked исключение NullPointerException

// ✅ Компилируется БЕЗ обработки (unchecked)
public void processString(String str) {
    System.out.println(str.length()); // Может выбросить NPE
}

// ✅ Можно обработать, но не обязательно
public void processStringWithHandling(String str) {
    try {
        System.out.println(str.length());
    } catch (NullPointerException e) {
        System.out.println("String is null");
    }
}

// ✅ Лучше - проверить перед использованием
public void processStringBetter(String str) {
    if (str != null) {
        System.out.println(str.length());
    }
}

Пример 3: Смешивание Checked и Unchecked

public class FileProcessor {
    // Checked исключение - должно быть в throws
    public void readAndProcess(String filename) throws IOException {
        // IOException - checked, должно быть обработано
        String content = Files.readString(Paths.get(filename));
        
        // NullPointerException - unchecked, не требует throws
        processContent(content);
    }
    
    // Unchecked исключение - не требует throws
    private void processContent(String content) {
        int length = content.length(); // Может быть NPE, но не требует throws
        System.out.println("Length: " + length);
    }
}

Таблица различий

ПараметрCheckedUnchecked
Наследованиеextends Exceptionextends RuntimeException
Обработка обязательна✅ ДА❌ НЕТ
Throws обязателен✅ ДА❌ НЕТ
Ошибка при игнорированииКомпиляцииRuntime
Когда выбрасываетсяPredictableUnpredictable
ПримерыIOException, SQLExceptionNullPointerException, ArithmeticException

Правила для throws

Правило 1: Checked исключения ВСЕГДА требуют throws

// ❌ ОШИБКА - IOException не обработано
public void readFile(String path) {
    String content = Files.readString(Paths.get(path)); // Ошибка!
}

// ✅ ПРАВИЛЬНО
public void readFile(String path) throws IOException {
    String content = Files.readString(Paths.get(path));
}

Правило 2: Unchecked исключения НЕ требуют throws

// ✅ ПРАВИЛЬНО - без throws
public void divide(int a, int b) {
    if (b == 0) throw new ArithmeticException("Cannot divide by zero");
    System.out.println(a / b);
}

// ✅ Тоже правильно - с throws (но не обязательно)
public void divideWithThrows(int a, int b) throws ArithmeticException {
    if (b == 0) throw new ArithmeticException("Cannot divide by zero");
    System.out.println(a / b);
}

Правило 3: Множественные исключения

// ❌ ОШИБКА - IOException не обработано
public void readMultipleFiles(String file1, String file2) {
    String content1 = Files.readString(Paths.get(file1));
    String content2 = Files.readString(Paths.get(file2));
}

// ✅ ПРАВИЛЬНО
public void readMultipleFiles(String file1, String file2) 
    throws IOException { // Один throws для всех IOException
    String content1 = Files.readString(Paths.get(file1));
    String content2 = Files.readString(Paths.get(file2));
}

// ✅ Или разные исключения
public void processData(String file) 
    throws IOException, SQLException {
    // файловые операции
    // и БД операции
}

Практический совет

// Когда использовать try-catch
public void processFileWithErrorHandling(String path) {
    try {
        String content = Files.readString(Paths.get(path));
        // Обработка
    } catch (IOException e) {
        // Обработка ошибки локально
        System.err.println("Failed to read: " + e.getMessage());
    }
}

// Когда использовать throws
public void processFilePassToUpper(String path) throws IOException {
    // Пробрасываем ошибку вверх по стеку
    // Ответственность на вызывающем коде
    String content = Files.readString(Paths.get(path));
}

// Когда использовать обоих
public void processFileHybrid(String path) throws IOException {
    try {
        String content = Files.readString(Paths.get(path));
        // Обработка
    } catch (IOException e) {
        // Логирование или дополнительная обработка
        logger.error("Error reading file", e);
        throw e; // Пробрасываем дальше
    }
}

Выводы

  1. Checked исключения (extends Exception) ТРЕБУЮТ обработки - ошибка компиляции
  2. Unchecked исключения (extends RuntimeException) НЕ ТРЕБУЮТ обработки
  3. Компилятор проверяет только checked исключения, unchecked он проверяет только в runtime
  4. Throws требуется для всех checked исключений, даже если они не обрабатываются
  5. Throws опционален для unchecked исключений, но может использоваться для документации
  6. Выбирайте checked исключения для предсказуемых ошибок (IO, SQL)
  7. Выбирайте unchecked исключения для программных ошибок (null, invalid args)
Всегда ли будет происходить ошибка компиляции при отсутствии обработки исключений, если в вызываемом методе используется throws? | PrepBro