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

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

1. Вступление

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

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

2. Throw иThrows

Начнем с краткого введения. Эти ключевые слова связаны с обработкой исключений. Exceptions are raised when the normal of flow of our application is disrupted.с

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

We use throw keyword to explicitly throw an exception из кода. Это может быть любой метод или статический блок. Это исключение должно быть подклассомThrowable.. Кроме того, оно может быть самимThrowable. Мы не можем генерировать несколько исключений с однимthrow.

Ключевое словоThrows может быть помещено в объявление метода. It denotes which exceptions can be thrown from this method. Мы должны обрабатывать эти исключения с помощью try-catch.

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

3. Throw в 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. Хорошая практика

We should always prefer the most specific exception. Нам нужно найти класс, который лучше всего подходит для нашего исключительного события. Например, throwNumberFormatException  вместоIllegalArgumentException. . Мы должны избегать использования неспецифическогоException.

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

public static Integer valueOf(String s) throws NumberFormatException

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

A good idea is to define our own, more descriptive exception. В нашем классе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();
}

Теперь вSimpleService вызовем функцию репозитория, которая может привести к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. Multi-Catch с 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. . Помните, чтоwe should always catch a more detailed exception first.

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

4. Throws в Java

Добавляемthrows to в объявление метода.

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

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

The method may throw multiple exceptions. Они разделяются запятыми в конце объявления метода. Мы можем поместить как отмеченные, так и непроверенные исключения вthrows. . Мы описали разницу между ними ниже.

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

A checked exception means that it’s checked at the compile time. Обратите внимание, что мы должны обработать это исключение. В противном случае метод должен указать исключение с помощью ключевого словаthrows.

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

Вот небольшой пример:

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

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

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

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

Напротив,unchecked exceptions aren’t checked at the compile time. 

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

Unchecked exceptions are thrown during runtime. Следующий код выдаст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 иthrows. . Мы рассмотрели основы использования и немного поговорили о передовых методах. Затем мы поговорили о отмеченные и непроверенные исключения.

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

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