JavaRush /Курсы /Java Collections /throwable, multiple exceptions, эксепшн внутри метода fin...

throwable, multiple exceptions, эксепшн внутри метода finalize

Java Collections
8 уровень , 5 лекция
Открыта

— Ага. Вот ты где. Я уже тебя обыскалась.

— Что-то случилось?

— Нет, но мы же занимаемся.

— Ок. Я тебя слушаю.

— Я хочу тебе рассказать об исключениях еще пару фактов:

В Java 7 конструкция try-catch была немного расширена за счет добавления «множественных catch». Смотри пример:

Java 5
try
{
  …
}
 catch (IOException ex) 
{
 logger.log(ex);
 throw ex;
}
 catch (SQLException ex) 
{
 logger.log(ex);
 throw ex;
}
Java 7
try
{
  …
}
 catch (IOException | SQLException ex) 
{
 logger.log(ex);
 throw ex;
}

— Т.е. теперь можно писать несколько исключений через ИЛИ ( «|» — это бинарный ИЛИ)?

— Да, правда, удобно?

— Гм. А какой тип будет у этого объекта-исключения внутри блока catch?

Ведь у IOException могут быть свои методы, а у SQLException – свои.

— Тип исключения будет такой же, как и у их общего класса-предка.

— Ага. Т.е. скорее всего Exeption или RuntimeException. Почему тогда просто не написать catch(Exception e)?

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

Т.е. такая схема призвана решить проблему дублирования catch-блоков кода для обработки разных ошибок.

— Ага. Понято. Спасибо, Элли.

— Это еще не все, я хочу еще рассказать немного про блок finally.

Как ты уже, наверное, знаешь, этот блок выполняется всегда.

Когда я говорю всегда, я имеют ввиду абсолютно всегда.

Пример:

Пример с finally
try
{
 return 1;
}
 finally
{
 return 0;
}

Тут есть return в блоке try и return в блоке finally. Так вот, результатом вызова метода будет число 0.

Блок finally выполнится, что бы ни произошло. А его метод return перезатер старое возвращаемое значение своим значением.

— Ясно.

Более того, метод может либо вернуть значение, либо выбросить исключение.

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

— А если в блоке try выбрасывается исключение, а в блоке finally выполняется return?

Тогда считается, что метод корректно отработал и возвращается значение, которое было передано в return.

Пример Результа
try
{
 return 1;
}
 finally
{
 return 0;
}
0
try
{
 return 1;
}
 finally
{
 throw new RuntimeException();
}
RuntimeException
try
{
 throw new RuntimeException();
}
 finally
{
 return 0;
}
0
try
{
 throw new RuntimeException();
}
 finally
{
 throw new IOException();
}
IOException

Единственной причиной, по которой может не выполниться метод finally, может быть немедленное завершение программы посредством вызова метода System.exit();

Пример
try
{
 System.exit(0);
 return 1;
}
 finally
{
 return 0;
}

— Ясно.

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

Комментарии (20)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Long_byte Уровень 54
16 октября 2024
как работает вообще механизм блока finally?
Андрей Уровень 51
21 мая 2024
еще finally может не выполниться в потоках-демонах, если они завершат работу вместе с главным потоком
Fl1s Уровень 51
26 марта 2024
Ужс
Kurama Уровень 50
7 апреля 2023
Ладно, этого я не знал
lightning Уровень 41
26 августа 2021
— Гм. А какой тип будет у этого объекта-исключения внутри блока catch? Ведь у IOException могут быть свои методы, а у SQLException – свои. — Тип исключения будет такой же, как и у их общего класса-предка. Стоит добавить, что класс предка будет использоваться только в пределах блока catch в котором перехвачено исключение. Если пробросить его дальше, то оно будет иметь исходный тип. Даже если перехватывать Exception и пробрасывать его далее, то в вышестоящем методе исключение будет иметь исходный тип. Т.е. нижеприведенный код будет выводить :

void f() {
      if (((int) (Math.random() * 2)) ==1 ) throw new NullPointerException();
      else throw new ArrayIndexOutOfBoundsException();
}

void g() {
      try {
          f();
      }
      catch (NullPointerException | ArrayIndexOutOfBoundsException e) {
          throw e;
      }
 }

void j() {
      try {
          g();
      }
      catch (NullPointerException e) {
          System.out.println("NullPointerException");
      }
      catch (ArrayIndexOutOfBoundsException e) {
          System.out.println("ArrayIndexOutOfBoundsException");
      }
}
Pig Man Уровень 41
23 февраля 2021
Предыдущая лекция: "Считать исключение ошибками – это неверный подход" Эта лекция: "Когда программисты обрабатывают все ошибки отдельно" Как людям правильно соблюдать терминологию, если даже учителя ее не соблюдают?
Андрей Уровень 41
5 февраля 2021
Javarush, посмотрите эту страницу. На ней куча опечаток. Пожалуйста исправьте.
Ars Уровень 41
29 ноября 2021
Всё ещё не везде исправили. Например в предпоследнем блоке кода столбец называется "Результа"
skrskr Уровень 39
5 февраля 2020
Есть объяснение почему нельзя использовать сокращённые операторы, а не только побитовые?
Илья Уровень 41
18 февраля 2021
ты написал одно и тоже))))
LuneFox Уровень 41 Expert
8 марта 2022
Он разное написал. Сокращённый это ||, а под побитовым имеется в виду |.
Игорь Уровень 41
14 июня 2019
А где про эксепшн внутри метода finalize?
7 апреля 2020
Видимо опечатались в названии лекции. Вот может кому понадобиться. Вопрос Что произойдет со сборщиком мусора (GC), если во время выполнения метода finalize() некоторого объекта произойдет исключение? Ответ Во время старта JVM запускается поток finalizer, который работает в фоне. Этот поток имеет метод runFinalizer, который игнорирует все исключения методов finalize объектов перед сборкой мусора. То есть если во время выполнения метода finalize возникнет исключительная ситуация, его выполнение будет остановлено и это никак не скажется на работоспособности самого сборщика мусора (garbage collector). http://www.quizful.net/interview/java/exception-while-finalize
Пётр Уровень 41 Expert
26 апреля 2019
finally, насколько помню, не выполняется при System.exit(0) или (-1) в catche или основном коде