Ключевые слова throw и throws часто вызывают путаницу, особенно при собеседованиях. Они относятся к исключениям, но используются в разных контекстах. throw применяется для создания и выброса конкретного исключения во время выполнения программы, тогда как throws указывает, что метод может передавать исключения выше по стеку вызовов. Мы подробно рассмотрим различия между throw и throws и разберем некоторые типичные вопросы на собеседованиях.
Если вы хотите глубже изучить Java, стоит обратиться в учебный центр FoxmindEd, который предлагает структурированные курсы и квалифицированных преподавателей.
Что такое throw ?
throw — это оператор в Java, который используется для генерации исключений во время выполнения программы. Благодаря throw можно сознательно вызвать исключительную ситуацию, когда программа сталкивается с неожиданными или некорректными входными данными.
public class Main {
public static void main(String[] args) {
AgeValidator.validateAge(20); // -> Age accepted: 20
AgeValidator.validateAge(16); // -> IllegalArgumentException will be thrown
}
}
class AgeValidator {
public static void validateAge(int age) {
if (age < 18) {
throw new IllegalArgumentException("The age must be 18 or older!");
}
System.out.println("Age accepted: " + age);
}
}
В этом коде, если возраст меньше 18, мы явно выбрасываем IllegalArgumentException с помощью throw. Это распространенный прием для валидации входных данных.
На собеседованиях могут спросить:
- Можно ли использовать throw без экземпляра исключения? — Нет, нужно передать объект, который является экземпляром Throwable.
public class Main {
public static void main(String[] args) {
throw; // Compilation error "unexpected token"
}
}
- Можете ли вы сделать исключение без нового?
Нет, поскольку исключение — это объект, его нужно явно создать через new.
- Можно ли выбросить собственный класс из-за броска?
Да, если этот класс наследует Throwable или Exception.
- Можно ли передавать throw строку или число?
Нет, можно передавать только объекты, которые являются подклассами Throwable.
Что такое throws?
В отличие от throw, который используется для создания и выброса исключения, throws не вызывает исключение напрямую, а только сообщает, что метод потенциально может его выбросить, и используется в сигнатуре метода.
Если метод может вызвать проверенное исключение (Checked Exception), его нужно либо обработать внутри метода с помощью try-catch, либо задекларировать в throws, передав обработку на уровень вызывающего кода. Ключевое слово throws работает только с проверенными (Checked) исключениями, поскольку они требуют обязательной обработки. Непроверенные (Unchecked) исключения, такие как NullPointerException или ArithmeticException, не требуют декларации в throws, поскольку Java позволяет выбрасывать их в любом месте без предупреждения компилятора.
public class Main {
public static void main(String[] args) {
try {
FileProcessor.readFile("someFile.txt");
} catch (IOException e) {
System.out.println("Error wile file reading: " + e.getMessage());
}
}
}
class FileProcessor {
public static void readFile(String filePath) throws IOException {
FileReader fileReader = new FileReader(filePath);
BufferedReader bufferedReader = new BufferedReader(fileReader);
System.out.println("File was opened: " + filePath);
bufferedReader.close();
}
}
Рассмотрим метод readFile(), который пытается открыть файл. Поскольку операции ввода/вывода могут вызвать IOException, мы декларируем это исключение с помощью throws, чтобы обработать его на уровне вызова.
- Почему мы не добавляем try-catch непосредственно в метод readFile()?
Если метод readFile() содержал бы try-catch, он должен был бы самостоятельно обрабатывать ошибки, что могло бы быть неприемлемым в различных сценариях использования. Ведь разные части программы могут по-разному реагировать на отсутствие файла: в одном случае может потребоваться просто выбросить исключение и остановить выполнение, в другом — попытаться открыть резервный файл, а в третьем — уведомить пользователя и предложить ввести другой путь. Используя throws, мы предоставляем гибкость пользователям нашего метода: они сами решают, как реагировать на исключительную ситуацию, и могут выбрать наиболее подходящий способ ее обработки. Также таким образом мы разделяем ответственность — метод readFile() отвечает только за чтение файла, а не за обработку ошибок.
Если метод может выбрасывать несколько исключений, они перечисляются через запятую:
public static void methodName(String someParameter) throws IOException, SQLException {
// method logic
}
Что могут спросить на собеседовании?
- Можно ли использовать throws для RuntimeException?
Да, но это не обязательно. Непроверенные исключения(Unchecked Exceptions), такие как NullPointerException или IllegalArgumentException, можно не декларировать в throws, поскольку компилятор этого не требует.
- Можно ли переопределить метод (override), не указав throws, если он есть в родительском классе?
Да, но только если переопределенный метод либо не выбрасывает исключения вообще, либо выбрасывает исключения того же типа или их подклассы
- Наследуют ли подклассы исключения, указанные в throws в родительском классе?
Если метод родительского класса декларирует проверенное исключение (Checked Exception) в throws, то переопределенный метод в подклассе не обязан указывать это исключение.
Однако, если он все же отмечает throws, то он может либо повторить исключения родительского метода, либо указать его подкласс. Но нельзя добавлять новые исключения, которые не присутствуют в родительском методе (за исключением непроверенных RuntimeException).
class Parent {
public void readFile() throws IOException {
// Method logic
}
public void processData() throws IOException {
// Method logic
}
public void connectToDatabase() throws IOException {
// Method logic
}
}
class Child extends Parent {
// You can declare the same exception or its subclass.
@Override
public void readFile() throws FileNotFoundException {
System.out.println("Override with FileNotFoundException");
}
// Exception cannot be thrown in the overridden method
@Override
public void processData() {
System.out.println("Override without exception");
}
// Compilation error: You cannot add a new checked exception that is not in the parent method
@Override
public void connectToDatabase() throws SQLException {
System.out.println("Override with SQLException");
}
}
Хотите узнать больше, что такое throw и throws в Java? Задайте свой вопрос в комментариях ниже! 🤔👇👇