- Исключения, try . catch
- Ключевые слова исключений try, catch, throw, throws, finally
- Типы исключений
- Неперехваченные исключения
- Перехват исключений try/catch
- Несколько разделов catch
- Вложенные операторы try
- Возбуждение исключений throw
- Объявление об исключении throws
- Ключевое слово finally
- Наследование исключений
- Множественные исключения
- The catch Blocks
- Catching More Than One Type of Exception with One Exception Handler
- Java catch base exception
Исключения, try . catch
В данной статье рассматривается используемый в Java механизм обработки исключений. Исключение в Java — это объект, который описывает исключительное состояние, возникшее в каком-либо участке программного кода. Когда возникает исключительное состояние, создается объект класса Exception. Этот объект пересылается в метод, обрабатывающий данный тип исключительной ситуации. Исключения могут возбуждаться и для того, чтобы сообщить о некоторых нештатных ситуациях.
Ключевые слова исключений try, catch, throw, throws, finally
Механизм исключительных ситуаций в Java поддерживается пятью ключевыми словами:
Ниже приведена общая форма блока обработки исключений.
try < // блок кода >catch ( е) < // обработчик исключений типа ExceptionType1 >catch ( е) < // обработчик исключений типа ExceptionType2 >finally < // . >
Типы исключений
В вершине иерархии исключений стоит класс Throwable, который наследуется от Object. Каждый из типов исключений является подклассом Throwable. Два непосредственных наследника класса Throwable делят иерархию подклассов исключений на две различные ветви. Иерархия классов представлена на рисунке.
Класс Ехception используется для описания исключительных ситуации, которые должны перехватываться программным кодом пользователя. Класс Error предназначен для описания исключительных ситуаций, которые при обычных условиях не должны перехватываться в пользовательской программе.
Неперехваченные исключения
Объекты-исключения автоматически создаются исполняющей средой Java в результате возникновения определенных исключительных ситуаций. Пример программы, в которой создаем исключительную ситуацию при делении на нуль.
package samples; class TestException < public static void main(String args[]) < int d = 0; int a = 42 / d; System.out.println ("a = " + a); >>
В консоль будет выведено следующее сообщение.
Exception in thread "main" java.lang.ArithmeticException: / by zero at samples.TestException.main(TestException.java:8)
Следует обратить внимание на тот факт, что типом возбужденного исключения был не Exception и не Throwable. Это подкласс класса Exception, а именно: ArithmeticException, поясняющий, какая ошибка возникла при выполнении программы.
Изменим класс добавлением статического метода subroutine, в котором создадим такую же исключительную ситуацию.
package samples; public class TestException < static void subroutine() < int d = 0; int a = 10 / d; System.out.println ("a = " + a); >public static void main(String[] args) < TestException.subroutine(); >>
Сообщение выполнения программы показывает, как обработчик исключений исполняющей системы Java выводит содержимое всего стека вызовов.
Exception in thread "main" java.lang.ArithmeticException: / by zero at samples.TestException.subroutine(TestException.java:8) at samples.TestException.main(TestException.java:14)
Перехват исключений try/catch
Для защиты программного кода от исключений необходимо использовать связанные блоки с ключевыми словами try catch; catch помещается сразу же после try-блока. В блоке catch задается тип исключения, которое необходимо обработать.
class TestException < public static void main(String args[]) < try < int d = 0; int a = 42 / d; >catch (ArithmeticException e) < System.out.println("division by zero"); >> >
Целью большинства хорошо сконструированных catch-разделов должна быть обработка возникшей исключительной ситуации и приведение переменных программы в некоторое разумное состояние — такое, чтобы программу можно было продолжить так, будто никакой ошибки и не было (в нашем примере выводится предупреждение — division by zero).
Несколько разделов catch
В отдельных случаях блок программного кода может вызвать исключения различных типов. Для того, чтобы локализовать обработку подобных ситуаций, можно использовать несколько catch-разделов для одного try-блока. Блоки наиболее специализированных классов исключений должны идти первыми, поскольку ни один подкласс не будет достигнут, если поставить его после суперкласса.
В следующем примере перехватывается два различных типа исключений, причем за этими двумя специализированными обработчиками следует раздел catch общего назначения, перехватывающий все подклассы класса Throwable.
class MultiCatch < static int c[] = < 1 >; public static void main(String args[]) < try < int a = args.length; System.out.println("a = " + String.valueOf(a)); int b = 23 / a; c[4] = 33; >catch (ArithmeticException e) < System.out.println("ArithmeticException : " + e.getMessage()); >catch(ArrayIndexOutOfBoundsException e) < System.out.println( "ArrayIndexOutOfBoundsException : " + e.getMessage()); >> >
Данный пример, запущенный без параметров, вызывает возбуждение исключительной ситуации деления на нуль. Если в командной строке будет определен один или несколько параметров, тем самым установив ‘а’ в значение больше нуля, то будет возбуждено исключение выхода индекса за границы массива ArrayIndexOutOfBounds. Ниже приведены результаты работы этой программы, запущенной и тем и другим способом.
а = 0 div by 0: java.lang.ArithmeticException: / by zero a = 1 array index oob: java.lang.ArrayIndexOutOfBoundsException:33
Вложенные операторы try
Операторы try можно вкладывать друг в друга. Если у оператора try низкого уровня нет раздела catch, соответствующего возбужденному исключению, стек будет развернут на одну ступень выше, и в поисках подходящего обработчика будут проверены разделы catch внешнего оператора try. Пример вложения двух операторов try catch друг в друга посредством вызова метода.
class MultiNest < static int c[] = < 1 >; static void checkArray() < try < c[4] = 33; >catch(ArrayIndexOutOfBoundsException e) < System.out.println "ArrayIndexOutOfBoundsException : " + e.getMessage()); >> public static void main(String args[]) < try < int a = args.length(); System.out.println("a = " + a); int b = 23 / a; checkArray(); >catch (ArithmeticException e) < System.out.println("ArithmeticException : " + e.getMessage()); >> >
Возбуждение исключений throw
Программа может явно вызывать исключение, используя оператор throw. После выполнения оператора throw процесс выполнения программы приостанавливается и последующие операторы не выполняются. JVM просматривает ближайший блоки try . catch, соответствующий типу исключения, для «передачи управления». Если подходящий блок не будет найден, то обработчик исключений остановит программу и «распечатает» при этом состояние стека вызовов.
Пример исключения, в котором сначала создается объект-исключение, затем оператор throw возбуждает исключительную ситуацию, после чего то же исключение возбуждается повторно — на этот раз уже кодом перехватившего его в первый раз раздела catch.
class TestThrow < static void method() < try < throw new NullPointerException("Exception in method"); >catch (NullPointerException e) < System.out.println(e.getMessage()); throw e; >> public static void main(String args[]) < try < method(); >catch(NullPointerException e) < System.out.println("Catch inside main : " + e.getMessage()); >> >
Результат выполнения программы приведен ниже.
Exception in method Catch inside main : Exception in method
Объявление об исключении throws
Если метод может возбуждать исключения, которые сам не обрабатывает, то он должен объявить об этом, чтобы вызывающие его другие методы могли защитить себя от этих исключений. Для задания списка исключений, которые могут возбуждаться методом, используется ключевое слово throws.
Если метод в явном виде (т.е. с помощью оператора throw) возбуждает исключение, тип класса исключений должен быть указан в операторе throws в объявлении этого метода. Принимая данное положение во внимание синтаксис определения метода должен быть описан следующим образом:
public class TestThrow < static void method() throws IllegalAccessException < try < System.out.println("inside method"); throw new IllegalAccessException ( "Exception in method"); >catch (NullPointerException e) < System.out.println(e.getMessage()); >> public static void main(String args[]) < try < method(); >catch(IllegalAccessException e) < System.out.println("Catch inside main : " + e.getMessage()); >> >
inside method Catch inside main : Exception in method
Ключевое слово finally
В случае, когда необходимо гарантировано выполнить определенный участок кода необходимо использовать ключевое слово finally. Использование связи try. finally позволяет обеспечить выполнение кода независимо от того, какие исключения были возбуждены и перехвачены, даже в тех случаях, когда в методе нет соответствующего возбужденному исключению раздела catch.
У каждого раздела try должен быть по крайней мере или один раздел catch или блок finally. Блок finally очень удобен для закрытия файлов и освобождения любых других ресурсов, захваченных для временного использования в начале выполнения метода.
Ниже приведен пример класса с двумя методами, завершение которых происходит по разным причинам, но в обоих перед выходом выполняется код раздела finally.
public class TestFinally < static void methodA() < try < System.out.println("inside methodA"); throw new RuntimeException("Exception in methodA"); >finally < System.out.println("finally inside methodA"); >> static void methodB() < try < System.out.println("inside methodB"); return; >finally < System.out.println("finally inside methodB"); >> public static void main(String args[]) < try < methodA(); >catch (Exception e) < System.out.println("Catch exception iinside main"); >methodB(); > >
В тестовом примере в методе methodA возбуждается исключение. Но перед преждевременным выходом из блока try, выполняется раздел finally. Во втором методе methodB завершается работа в try-блоке оператором return, но и при этом перед выходом из метода выполняется программный код блока finally. Результат работы тестового примера:
inside methodA finally inside methodA Catch exception iinside main inside methodB finally inside methodB
Обработка исключений в Java предоставляет исключительно мощный механизм для управления сложными программами. Ключевые слова try, throw, catch позволяют выполнять обработку ошибок и разных нештатных ситуаций в программе.
Наследование исключений
catch — полиморфная конструкция, т.е. catch по типу parent перехватывает исключения любого типа, которые является Parent’ом.
public class TestException < public static void main(String[] args) < try < System.err.print("level 0"); throw new RuntimeException(); System.err.print("level 1"); >catch (Exception e) < // catch Exception ПЕРЕХВАТ RuntimeException System.err.print("level 2"); >System.err.println("level 3"); > >
В результате в консоли увидим
Error и Exception из параллельных веток наследования от Throwable, поэтому catch по одному «брату» не может поймать другого «брата».
public class TestError < public static void main(String[] args) < try < System.err.println("level 0"); if (true) < throw new Error(); >System.err.println("level 1"); > catch (Exception e) < System.err.println("level 2"); >System.err.println("level 3"); > >
Результат выполения программы
level 0 Exception in thread "main" java.lang.Error at TestError.main(TestFinally.java:8)
Множественные исключения
Объявление исключений в методе может быть множественным. Пример :
import java.io.EOFException; import java.io.FileNotFoundException; public class MultiException < // объявляем исключения public static void main(String[] args) throws EOFException, FileNotFoundException < if (System.currentTimeMillis() % 2 == 0) < throw new EOFException(); >else < throw new FileNotFoundException(); >> >
The catch Blocks
You associate exception handlers with a try block by providing one or more catch blocks directly after the try block. No code can be between the end of the try block and the beginning of the first catch block.
try < >catch (ExceptionType name) < >catch (ExceptionType name)
Each catch block is an exception handler that handles the type of exception indicated by its argument. The argument type, ExceptionType , declares the type of exception that the handler can handle and must be the name of a class that inherits from the Throwable class. The handler can refer to the exception with name .
The catch block contains code that is executed if and when the exception handler is invoked. The runtime system invokes the exception handler when the handler is the first one in the call stack whose ExceptionType matches the type of the exception thrown. The system considers it a match if the thrown object can legally be assigned to the exception handler’s argument.
The following are two exception handlers for the writeList method:
try < >catch (IndexOutOfBoundsException e) < System.err.println("IndexOutOfBoundsException: " + e.getMessage()); >catch (IOException e)
Exception handlers can do more than just print error messages or halt the program. They can do error recovery, prompt the user to make a decision, or propagate the error up to a higher-level handler using chained exceptions, as described in the Chained Exceptions section.
Catching More Than One Type of Exception with One Exception Handler
In Java SE 7 and later, a single catch block can handle more than one type of exception. This feature can reduce code duplication and lessen the temptation to catch an overly broad exception.
In the catch clause, specify the types of exceptions that block can handle, and separate each exception type with a vertical bar ( | ):
catch (IOException|SQLException ex)
Note: If a catch block handles more than one exception type, then the catch parameter is implicitly final . In this example, the catch parameter ex is final and therefore you cannot assign any values to it within the catch block.
Java catch base exception
правильно ли понимаю, что когда я работаю с проектом, в котором есть несколько потоков исполнения, может быть вот такая ситуация. Один из этих потоков запускается и завершается успешно, а затем выбрасывает исключение внутри блока try-catch. Оставшиеся потоки исполнения продолжают свою работу, но никакой код в блоке finally не выполняется. Тогда блок finally при обработке исключений не будет выполнен?
я читаю про исключения на 1м и в принципе понимаю, но не очень. ps: зачем только я начал с java core. pss: если вы это читаете, и я до сих пор на первом, то либо я прохожу другой курс, либо читаю книгу по джаве, параллельно проходя этот курс, либо решил взять перерыв на неопределенный срок времени. никогда не сдамся)
Есть подозрение, что так будет правильнее.
обращу внимание на некоторую неточность. цитата «Создание исключения При исполнении программы исключение генерируется JVM или вручную, с помощью оператора throw» в java исключения это тоже объекты поэтому создается исключение так же как объект new Exception. а бросается в программе с помощью оператора throw. обычно эти операции объединяют в одну throw new Exception(«aaa»);
если что я пишу это с 3 уровня. Под конец лекций я читал статью про бафридер, после нашел там ссылку на потоки вводов, а потом чтобы понять что там говориться ввел гугл про исключение и нашел эту статью, спасибо автору, это статья очень помогла. PS если ты читаешь этот комментарий и видишь что у меня нет прогресса(то есть если я все еще на 3 уровне или чуточку больше), то скажи мне, что я нуб и не дошел до 40 лвла