Рубрики
Без рубрики

Разница между броском и бросками в Java

Исследуйте разницу между двумя ключевыми словами Java: throw и throws.

Автор оригинала: baeldung.

1. введение

В этом уроке мы рассмотрим throw и throw в Java. Мы объясним, когда нам следует использовать каждый из них.

Далее мы покажем несколько примеров их основного использования.

2. Бросок и броски

Давайте начнем с краткого введения. Эти ключевые слова связаны с обработкой исключений. Исключения возникают, когда нарушается нормальный поток нашего приложения.

Причин может быть много. Пользователь может отправить неверные входные данные. Мы можем потерять связь или может возникнуть другая неожиданная ситуация. Хорошая обработка исключений-это ключ к тому, чтобы наше приложение работало после появления этих неприятных моментов.

Мы используем ключевое слово throw для явного исключения из кода. Это может быть любой метод или статический блок. Это исключение должно быть подклассом Throwable. Кроме того, это может быть Бросаемый сам по себе. Мы не можем выбрасывать несколько исключений с помощью одного throw .

Ключевое слово может быть помещено в объявление метода. Он обозначает, какие исключения могут быть вызваны из этого метода. Мы должны обрабатывать эти исключения с помощью try-catch.

Эти два ключевых слова не взаимозаменяемы!

3. Бросьте в Java

Давайте рассмотрим базовый пример с выбрасыванием исключения из метода.

Прежде всего, представьте, что мы пишем простой калькулятор. Одной из основных арифметических операций является деление. В связи с этим нас попросили реализовать эту функцию:

public double divide(double a, double b) {
    return a / b;
}

Поскольку мы не можем делить на ноль, нам нужно добавить некоторые изменения в наш существующий код. Похоже, это хороший момент для создания исключения.

Давайте сделаем это:

public double divide(double a, double b) {
    if (b == 0) {
        throw new ArithmeticException("Divider cannot be equal to zero!");
    }
    return a / b;
}

Как вы можете видеть, мы использовали ArithmeticException , который идеально соответствует нашим потребностям. Мы можем передать один параметр конструктора String , который является сообщением об исключении.

3.1. Надлежащая практика

Мы всегда должны предпочесть самое конкретное исключение. Нам нужно найти класс, который лучше всего подходит для нашего исключительного события. Например, бросьте NumberFormatException вместо Исключение IllegalArgumentException. Мы должны избегать создания неспецифического Исключения .

Например, в пакете java.lang есть класс Integer . Давайте взглянем на одно из объявлений заводского метода:

public static Integer valueOf(String s) throws NumberFormatException

Это статический фабричный метод, который создает Integer экземпляр из String. В случае неправильного ввода String метод вызовет исключение NumberFormatException.

Хорошая идея-определить наше собственное, более описательное исключение. В нашем классе Calculator это может быть, например, исключение DivideByZeroException.

Давайте рассмотрим пример реализации:

public class DivideByZeroException extends RuntimeException {

    public DivideByZeroException(String message) {
        super(message);
    }
}

3.2. Обертывание существующего исключения

Иногда мы хотим обернуть существующее исключение в определенное нами исключение.

Давайте начнем с определения вашего собственного исключения:

public class DataAcessException extends RuntimeException {
    
    public DataAcessException(String message, Throwable cause) {
        super(message, cause);
    }
}

Конструктор принимает два параметра: сообщение об исключении и причину, которая может быть любым подклассом Throwable.

Давайте напишем поддельную реализацию для функции findAll() :

public List findAll() throws SQLException {
    throw new SQLException();
}

Теперь в Simple Service вызовем функцию репозитория, которая может привести к SQLException:

public void wrappingException() {
    try {
        personRepository.findAll();
    } catch (SQLException e) {
        throw new DataAccessException("SQL Exception", e);
    }
}

Мы повторно выбрасываем SQLException , завернутый в наше собственное исключение, называемое DataAccessException. Все проверяется следующим тестом:

@Test
void whenSQLExceptionIsThrown_thenShouldBeRethrownWithWrappedException() {
    assertThrows(DataAccessException.class,
      () -> simpleService.wrappingException());
}

Для этого есть две причины. Прежде всего, мы используем перенос исключений, потому что остальной части кода не нужно знать о каждом возможном исключении в системе.

Кроме того, компонентам более высокого уровня не нужно знать ни о компонентах нижнего уровня, ни об исключениях, которые они выбрасывают.

3.3. Мульти-улов с Java

Иногда методы, которые мы используем, могут вызывать множество различных исключений.

Давайте взглянем на более обширный блок try-catch:

try {
    tryCatch.execute();
} catch (ConnectionException | SocketException ex) {
    System.out.println("IOException");
} catch (Exception ex) {
    System.out.println("General exception");
}

Метод execute может вызывать три исключения: SocketException, ConnectionException, Exception. Первый блок catch поймает ConnectionException или SocketException . Второй блок catch будет перехватывать Exception или любой другой подкласс Exception. Помните, что мы всегда должны сначала поймать более подробное исключение.

Мы можем поменять порядок наших блоков улова. Тогда мы никогда не поймаем SocketException и ConnectionException , потому что все пойдет в ловушку с Исключением .

4. Броски в Java

Мы добавляем throws к объявлению метода.

Давайте взглянем на одно из наших предыдущих объявлений метода:

public static void execute() throws SocketException, ConnectionException, Exception

Метод может вызывать несколько исключений. Они разделяются запятыми в конце объявления метода. Мы можем поместить как проверенные, так и непроверенные исключения в броски. Мы описали разницу между ними ниже.

4.1. Проверенные и Непроверенные исключения

Проверенное исключение означает, что оно проверяется во время компиляции. Обратите внимание, что мы должны обработать это исключение. В противном случае метод должен указать исключение с помощью ключевого слова throws .

Наиболее распространенными проверяемыми исключениями являются Исключение IOException, исключение FileNotFoundException, исключение ParseException. FileNotFoundException может быть вызвано при создании FileInputStream из файла.

Вот короткий пример:

File file = new File("not_existing_file.txt");
try {
    FileInputStream stream = new FileInputStream(file);
} catch (FileNotFoundException e) {
    e.printStackTrace();
}

Мы можем избежать использования блока try-catch, добавив throws в объявление метода:

private static void uncheckedException() throws FileNotFoundException {
    File file = new File("not_existing_file.txt");
    FileInputStream stream = new FileInputStream(file);
}

К сожалению, функция более высокого уровня все еще должна обрабатывать это исключение. В противном случае мы должны поместить это исключение в объявление метода с ключевым словом throws.

Напротив, непроверенные исключения не проверяются во время компиляции.

Наиболее распространенными непроверенными исключениями являются: ArrayIndexOutOfBoundsException, IllegalArgumentException, NullPointerException.

Непроверенные исключения создаются во время выполнения. Следующий код вызовет исключение NullPointerException. Вероятно, это одно из самых распространенных исключений в Java.

Вызов метода по нулевой ссылке приведет к этому исключению:

public void runtimeNullPointerException() {
    String a = null;
    a.length();
}

Давайте проверим это поведение в тесте:

@Test
void whenCalled_thenNullPointerExceptionIsThrown() {
    assertThrows(NullPointerException.class,
      () -> simpleService.runtimeNullPointerException());
}

Пожалуйста, помните, что этот код и тест не имеют никакого смысла. Это только в учебных целях, чтобы объяснить исключения во время выполнения.

В Java каждый подкласс Error и RuntimeException является непроверенным исключением. Проверенное исключение-это все остальное в классе Throwable .

5. Заключение

В этой статье мы обсудили разницу между двумя ключевыми словами Java: throw и throw. Мы прошли через основное использование и немного поговорили о хороших практиках . Затем мы говорили о проверенных и непроверенных исключениях.

Как всегда, исходный код можно найти на нашем GitHub .

Если вы хотите углубиться в обработку исключений в Java, пожалуйста, ознакомьтесь с нашей статьей об исключениях Java .