Обработка исключений Java: try-catch-finally
В предыдущих уроках я рассмотрел блок try-catch и вложенный блок try. В этом руководстве мы увидим блок finally, который используется вместе с try-catch. Он содержит все важные операторы, которые должны быть выполнены независимо от того, происходит ли исключение.
Синтаксис
Простой пример
Здесь вы можете видеть, что исключение произошло в блоке try, который был обработан в блоке catch, после того, как этот блок finally был выполнен.
class Example < public static void main(String args[]) < try< int num=121/0; System.out.println(num); >catch(ArithmeticException e) < System.out.println("Number should not be divided by zero"); >/* Finally block will always execute * even if there is no exception in try block */ finally < System.out.println("This is finally block"); >System.out.println("Out of try-catch-finally"); > >
Number should not be divided by zero This is finally block Out of try-catch-finally
Несколько важных моментов
- Блок finally должен быть связан с блоком try, нельзя использовать его без try. Вы должны поместить в этот блок те операторы, которые должны выполняться всегда.
- Блок finally не является обязательным, как мы видели в предыдущих уроках. Try-catch достаточен для обработки исключений, однако, если вы поместите finally, он всегда будет выполняться после выполнения try.
- В нормальном случае, когда в блоке try нет исключения, тогда блок finally выполняется после блока try. Однако, если возникает, catch выполняется перед finally.
- Исключение в блоке finally работает точно так же, как и любое другое.
- Операторы, присутствующие в блоке finally, выполняются, даже если try содержит операторы передачи управления, такие как return, break или continue.
Пример с оператором return
Хотя у нас есть метод return, блок finally все равно выполняется.
class JavaFinally < public static void main(String args[]) < System.out.println(JavaFinally.myMethod()); >public static int myMethod() < try < return 112; >finally < System.out.println("This is Finally block"); System.out.println("Finally block ran even after return statement"); >> >
This is Finally block Finally block ran even after return statement 112
Случаи, когда не выполняется
Обстоятельствами, препятствующими выполнению кода в блоке finally, являются:
- окончание потока;
- использование системой метода exit();
- исключение, возникающее в блоке finally.
Оператор close()
Оператор close() используется для закрытия всех открытых потоков в программе. Хорошей практикой является использование внутри блока finally. Поскольку блок выполняется, даже если возникает исключение, вы можете быть уверены, что все входные и выходные потоки закрыты должным образом независимо от того, возникло исключение или нет.
. try < OutputStream osf = new FileOutputStream( "filename" ); OutputStream osb = new BufferedOutputStream(opf); ObjectOutput op = new ObjectOutputStream(osb); try< output.writeObject(writableObject); >finally < op.close(); >> catch(IOException e1) < System.out.println(e1); >.
Без блока catch
Блок try-finally возможен без блока catch.
. InputStream input = null; try < input = new FileInputStream("inputfile.txt"); >finally < if(input != null) < try < in.close(); >catch(IOException exp) < System.out.println(exp); >> > .
System.exit()
Оператор System.exit() ведет себя иначе, чем оператор return. Всякий раз, когда он вызывается в блоке try, finally не выполняется:
. try < //try block System.out.println("Inside try block"); System.exit(0) >catch(Exception exp) < System.out.println(exp); >finally < System.out.println("Java finally block"); >.
В приведенном выше примере, если System.exit(0) вызывается без каких-либо исключений, то, finally, не будет выполняться. Однако если при его вызове произойдет какое-либо исключение, будет выполнен блок finally.
Блок try-catch-finally
- Либо оператор try должен быть связан с блоком catch, либо с finally.
- Так как catch выполняет обработку исключений и finally выполняет очистку, лучший способ – использовать оба из них.
Примеры
Пример 1 : Демонстрируется работа блока finally, когда в блоке try не возникает исключение
class Example1 < public static void main(String args[])< try< System.out.println("First statement of try block"); int num=45/3; System.out.println(num); >catch(ArrayIndexOutOfBoundsException e) < System.out.println("ArrayIndexOutOfBoundsException"); >finally < System.out.println("finally block"); >System.out.println("Out of try-catch-finally block"); > >
First statement of try block 15 finally block Out of try-catch-finally block
Пример 2 : Показана работа блока finally, когда исключение не обрабатывается в блоке catch:
class Example2 < public static void main(String args[])< try< System.out.println("First statement of try block"); int num=45/0; System.out.println(num); >catch(ArrayIndexOutOfBoundsException e) < System.out.println("ArrayIndexOutOfBoundsException"); >finally < System.out.println("finally block"); >System.out.println("Out of try-catch-finally block"); > >
First statement of try block finally block Exception in thread "main" java.lang.ArithmeticException: / by zero at beginnersbook.com.Example2.main(Details.java:6)
Как видно, система сгенерировала сообщение об исключении, но перед этим успешно завершился блок finally.
Пример 3 : Когда исключение возникает в блоке try и обрабатывается должным образом в блоке catch:
class Example3 < public static void main(String args[])< try< System.out.println("First statement of try block"); int num=45/0; System.out.println(num); >catch(ArithmeticException e) < System.out.println("ArithmeticException"); >finally < System.out.println("finally block"); >System.out.println("Out of try-catch-finally block"); > >
First statement of try block ArithmeticException finally block Out of try-catch-finally block
Java try catch finally
Java try, catch and finally blocks help in writing the application code which may throw exceptions in runtime and gives us a chance to either recover from exceptions by executing alternate application logic or handle the exception gracefully to report back to the user. It helps in preventing ugly application crashes.
Note that it is recommended to use the try-with-resources block everytime it is possible to use.
Before going deep into the concept, let us go through the very basic understanding of try-catch blocks and their syntax.
The try block contains the application code which is expected to work in normal conditions. For example, reading a file, writing to databases or performing complex business operations.
A try block is written with the try keyword followed by the curly braces.
The optional catch block(s) follows the try block and MUST handle the checked exceptions thrown by the try block and any possible unchecked exceptions.
An application can go wrong in N different ways. That’s why we can associate multiple catch blocks with a single try block. In each catch block, we can handle one or more specific exceptions in a unique way.
When one catch block handles the exception, the next catch blocks are not executed. Control shifts directly from the executed catch block to execute the remaining part of the program, including the finally block.
try < //code >catch(NullPointerException e) < //handle exception >catch(NumberFormatException e) < //handle exception >catch(Exception e) < //handle exception >
An optional finally block gives us a chance to run the code which we want to execute EVERYTIME a try-catch block is completed – either with errors or without any errors.
The finally block statements are guaranteed execution even if we fail to handle the exception successfully in catch block.
try < //open file //read file >catch(Exception e) < //handle exception while reading the file >finally < //close the file >
1.4. Only the try block is Mandatory
Please note that only try block is mandatory while catch and finally blocks are optional. With a try block, we can use either a catch block or finally block as needed.
It is possible to have below given both combinations in Java. Both versions are valid.
2. How an exception floats in Java?
Under normal circumstances, when there is an exception occurred during runtime, JVM wraps the error information in an instance of the sub-type of Throwable. This exception object is similar to other Java objects and has fields and methods.
Only difference is that JVM checks their presence and passes control to catch block which can handle this exception type or its parent class types.
When in the application, there is no catch block found for an exception, the uncaught exception is handled by a default exception handler at JVM level. It reports the exception to the user and terminates the application.
3. Different execution flows with try, catch and finally blocks
Let’s see some examples to understand how the executions will flow in different cases.
3.1. try, catch and finally blocks – NO exception occurred
If there is no exception occurred, then JVM will execute only finally block. The catch block will be skipped.
try < System.out.println("try block"); >catch (Exception e) < System.out.println("catch block"); >finally
3.2. try, catch and finally blocks – exception occurred
If there is an exception occurred in try block, then JVM will execute catch block first and then finally block.
try < System.out.println("try block"); throw new NullPointerException("Null occurred"); >catch (Exception e) < System.out.println("catch block"); >finally
try block catch block finally block
3.3. try and finally blocks – exception NOT handled
If the exception is not handled by any provided catch block, the JVM default exception handler handles it. In this case, finally block will be executed followed by the default exception handling mechanism.
try block finally block Exception in thread "main" java.lang.NullPointerException: Null occurred at com.howtodoinjava.Main.main(Main.java:12)
3.4. try, catch and finally blocks – multiple catch blocks
If there are multiple catch blocks associated with the try block, then the exception is handled by the first catch block in the sequence which can handle the exception type or its parent types.
For example, a catch block handling IOException, can handle the exceptions of type FileNotFoundException also because FileNotFoundException extends IOException .
try < System.out.println("try block"); throw new NullPointerException("null occurred"); >catch (NumberFormatException e) < System.out.println("catch block 1"); >catch (NullPointerException e) < System.out.println("catch block 2"); >catch (Exception e) < System.out.println("catch block 3"); >finally
try block catch block 2 finally block
3.5. try, catch and finally blocks – Exception is thrown from catch block
There may be cases when there is an exception while handling another exception in catch block. How will it handled?
In case of exception in the catch block, the execution is transferred to finally block (if any) associated with the respective catch block. Then the exception is propagated in the method call stack to find a catch block that can handle this exception.
If such catch block is found then exception is handled, else JVM default exception handler handles the exception and terminates the application.
try < System.out.println("try block"); throw new NullPointerException("NullPointerException occured"); >catch (NullPointerException e) < System.out.println("catch block 1"); throw new NumberFormatException("NumberFormatException occurred"); >catch (Exception e) < System.out.println("catch block 2"); >finally
try block catch block 1 finally block Exception in thread "main" java.lang.NumberFormatException: NumberFormatException occurred at com.howtodoinjava.Main.main(Main.java:18)
4. Java 7 try-with-resources
For AutoCloseable resources, such as streams, Java SE 7 introduced try-with-resources statements which is recommended ways to handle exceptions in mentioned scenarios. In this approach, we are not required to close the streams and JVM does it for us. It eliminates the need for finally blocks.
In try-with-resources, a resource is opened in try block inside small brackets and finally block is completely gone.
try (BufferedReader br = new BufferedReader(new FileReader("C:/temp/test.txt"))) < String sCurrentLine; while ((sCurrentLine = br.readLine()) != null) < System.out.println(sCurrentLine); >> catch (IOException e)
Try catch finally java пример
правильно ли понимаю, что когда я работаю с проектом, в котором есть несколько потоков исполнения, может быть вот такая ситуация. Один из этих потоков запускается и завершается успешно, а затем выбрасывает исключение внутри блока try-catch. Оставшиеся потоки исполнения продолжают свою работу, но никакой код в блоке finally не выполняется. Тогда блок finally при обработке исключений не будет выполнен?
я читаю про исключения на 1м и в принципе понимаю, но не очень. ps: зачем только я начал с java core. pss: если вы это читаете, и я до сих пор на первом, то либо я прохожу другой курс, либо читаю книгу по джаве, параллельно проходя этот курс, либо решил взять перерыв на неопределенный срок времени. никогда не сдамся)
Есть подозрение, что так будет правильнее.
обращу внимание на некоторую неточность. цитата «Создание исключения При исполнении программы исключение генерируется JVM или вручную, с помощью оператора throw» в java исключения это тоже объекты поэтому создается исключение так же как объект new Exception. а бросается в программе с помощью оператора throw. обычно эти операции объединяют в одну throw new Exception(«aaa»);
если что я пишу это с 3 уровня. Под конец лекций я читал статью про бафридер, после нашел там ссылку на потоки вводов, а потом чтобы понять что там говориться ввел гугл про исключение и нашел эту статью, спасибо автору, это статья очень помогла. PS если ты читаешь этот комментарий и видишь что у меня нет прогресса(то есть если я все еще на 3 уровне или чуточку больше), то скажи мне, что я нуб и не дошел до 40 лвла