What is Exception?

Exception is an event that interrupts the normal flow of execution. It is a disruption during the execution of the Java program.

In this tutorial, you will learn-

There are two types of errors:

  1. Compile time errors
  2. Runtime errors

Compile time errors can be again classified again into two types:

  • Syntax Errors
  • Semantic Errors

Syntax Errors Example:

Instead of declaring int a; you mistakenly declared it as in a; for which compiler will throw an error.

Example: You have declared a variable int a; and after some lines of code you again declare an integer as int a; . All these errors are highlighted when you compile the code.

Runtime Errors Example

A Runtime error is called an Exceptions error. It is any event that interrupts the normal flow of program execution.

Example for exceptions are, arithmetic exception, Nullpointer exception, Divide by zero exception, etc.

Exceptions in Java are something that is out of developers control.

Why do we need Exception?

Suppose you have coded a program to access the server. Things worked fine while you were developing the code.

During the actual production run, the server is down. When your program tried to access it, an exception is raised.

How to Handle Exception

So far we have seen, exception is beyond developer"s control. But blaming your code failure on environmental issues is not a solution. You need a Robust Programming, which takes care of exceptional situations. Such code is known as Exception Handler.

In our example, good exception handling would be, when the server is down, connect to the backup server.

To implement this, enter your code to connect to the server (Using traditional if and else conditions).

You will check if the server is down. If yes, write the code to connect to the backup server.

Such organization of code, using "if" and "else" loop is not effective when your code has multiple java exceptions to handle.

Class connect{ if(Server Up){ // code to connect to server } else{ // code to connect to BACKUP server } }

Try Catch Block

Java provides an inbuilt exceptional handling.

  1. The normal code goes into a TRY block.
  2. The exception handling code goes into the CATCH block

In our example, TRY block will contain the code to connect to the server. CATCH block will contain the code to connect to the backup server.

In case the server is up, the code in the CATCH block will be ignored. In case the server is down, an exception is raised, and the code in catch block will be executed.

So, this is how the exception is handled in Java.

Syntax for using try & catch

Try{ statement(s) } catch (exceptiontype name){ statement(s) }

Step 1) Copy the following code into an editor

Class JavaException { public static void main(String args){ int d = 0; int n = 20; int fraction = n/d; System.out.println("End Of Main"); } }

Step 2) Save the file & compile the code. Run the program using command, java JavaException

Step 3) An Arithmetic Exception - divide by zero is shown as below for line # 5 and line # 6 is never executed

Step 4) Now let"s see examine how try and catch will help us to handle this exception. We will put the exception causing the line of code into a try block, followed by a catch block. Copy the following code into the editor.

Class JavaException { public static void main(String args) { int d = 0; int n = 20; try { int fraction = n / d; System.out.println("This line will not be Executed"); } catch (ArithmeticException e) { System.out.println("In the catch Block due to Exception = " + e); } System.out.println("End Of Main"); } }

Step 5) Save, Compile & Run the code.You will get the following output

As you observe, the exception is handled, and the last line of code is also executed. Also, note that Line #7 will not be executed because as soon as an exception is raised the flow of control jumps to the catch block.

Note: The AritmeticException Object "e" carries information about the exception that has occurred which can be useful in taking recovery actions.

Java Exception class Hierarchy

After one catch statement executes, the others are bypassed, and execution continues after the try/catch block. The nested catch blocks follow Exception hierarchy.
  • All exception classes in Java extend the class ‘Throwable’. Throwable has two subclasses, Error and Exception
  • The Error class defines the exception or the problems that are not expected to occur under normal circumstances by our program, example Memory error, Hardware error, JVM error, etc
  • The Exception class represents the exceptions that can be handled by our program, and our program can be recovered from this exception using try and catch block
  • A Runtime exception is a sub-class of the exception class. The Exception of these type represents exception that occur at the run time and which cannot be tracked at the compile time. An excellent example of same is divide by zero exception, or null pointer exception, etc
  • IO exception is generated during input and output operations
  • Interrupted exceptions in Java, is generated during multiple threading.
Example: To understand nesting of try and catch blocks

Step 1)

Class JavaException { public static void main(String args) { try { int d = 1; int n = 20; int fraction = n / d; int g = { 1 }; g = 100; } /*catch(Exception e){ System.out.println("In the catch clock due to Exception = "+e); }*/ catch (ArithmeticException e) { System.out.println("In the catch clock due to Exception = " + e); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("In the catch clock due to Exception = " + e); } System.out.println("End Of Main"); } }

Step 2) Save the file & compile the code. Run the program using command, java JavaException .

Step 3) An ArrayIndexOutOfBoundsException is generated. Change the value of int d to 0. Save, Compile & Run the code.

Step 4 ) An ArithmeticException must be generated.

Step 5) Uncomment line #10 to line #12. Save, Compile & Run the code.

Step 6) Compilation Error? This is because Exception is the base class of ArithmeticException Exception. Any Exception that is raised by ArithmeticException can be handled by Exception class as well.So the catch block of ArithmeticException will never get a chance to be executed which makes it redundant. Hence the compilation error.

Java Finally Block

The finally block is executed irrespective of an exception being raised in the try block. It is optional to use with a try block.

Try { statement(s) } catch (ExceptiontType name) { statement(s) } finally { statement(s) }

In case, an exception is raised in the try block, finally block is executed after the catch block is executed.

Step 1) Copy the following code into an editor.

Class JavaException { public static void main(String args){ try{ int d = 0; int n =20; int fraction = n/d; } catch(ArithmeticException e){ System.out.println("In the catch clock due to Exception = "+e); } finally{ System.out.println("Inside the finally block"); } } }

Step 2) Save, Compile & Run the Code.

Step 3) Expected output. Finally block is executed even though an exception is raised.

Step 4) Change the value of variable d = 1. Save, Compile and Run the code and observe the output.Bottom of Form

Summary :

  • An Exception is a run-time error which interrupts the normal flow of program execution.Disruption during the execution of the program is referred as error or exception.
  • Errors are classified into two categories
    • Compile time errors – Syntax errors, Semantic errors
    • Runtime errors- Exception
  • A robust program should handle all exceptions and continue with its normal flow of program execution. Java provides an inbuilt exceptional handling method
  • Exception Handler is a set of code that handles an exception . Exceptions can be handled in Java using try & catch.
  • Try block : Normal code goes on this block.
  • Catch block : If there is error in normal code, then it will go into this block


2. Какова иерархия исключений.
3. Можно/нужно ли обрабатывать ошибки jvm?
4. Какие существуют способы обработки исключений?
5. О чем говорит ключевое слово throws?
6. В чем особенность блока finally? Всегда ли он исполняется?
7. Может ли не быть ни одного блока catch при отлавливании исключений?
8. Могли бы вы придумать ситуацию, когда блок finally не будет выполнен?
9. Может ли один блок catch отлавливать несколько исключений (с одной и разных веток наследований)?
10. Что вы знаете об обрабатываемых и не обрабатываемых (checked/unchecked) исключениях?
11. В чем особенность RuntimeException?
12. Как написать собственное (“пользовательское”) исключение? Какими мотивами вы будете руководствоваться при выборе типа исключения: checked/unchecked?
13. Какой оператор позволяет принудительно выбросить исключение?
14. Есть ли дополнительные условия к методу, который потенциально может выбросить исключение?
15. Может ли метод main выбросить исключение во вне и если да, то где будет происходить обработка данного исключения?
16. Если оператор return содержится и в блоке catch и в finally, какой из них “главнее”?
17. Что вы знаете о OutOfMemoryError?
18. Что вы знаете о SQLException? К какому типу checked или unchecked оно относится, почему?
19. Что такое Error? В каком случае используется Error. Приведите пример Error’а.
20. Какая конструкция используется в Java для обработки исключений?
21. Предположим, есть блок try-finally. В блоке try возникло исключение и выполнение переместилось в блок finally. В блоке finally тоже возникло исключение. Какое из двух исключений “выпадет” из блока try-finally? Что случится со вторым исключением?
22. Предположим, есть метод, который может выбросить IOException и FileNotFoundException в какой последовательности должны идти блоки catch? Сколько блоков catch будет выполнено?

Ответы

1. Дайте определение понятию “исключение”

Исключение — это проблема(ошибка) возникающая во время выполнения программы. Исключения могут возникать во многих случаях, например:

  1. Пользователь ввел некорректные данные.
  2. Файл, к которому обращается программа, не найден.
  3. Сетевое соединение с сервером было утеряно во время передачи данных. И т.д.

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

2. Какова иерархия исключений.

Исключения делятся на несколько классов, но все они имеют общего предка - класс Throwable. Его потомками являются подклассы Exception и Error.

Исключения (Exceptions) являются результатом проблем в программе, которые в принципе решаемые и предсказуемые. Например, произошло деление на ноль в целых числах.

Ошибки (Errors) представляют собой более серьёзные проблемы, которые, согласно спецификации Java, не следует пытаться обрабатывать в собственной программе, поскольку они связаны с проблемами уровня JVM. Например, исключения такого рода возникают, если закончилась память, доступная виртуальной машине. Программа дополнительную память всё равно не сможет обеспечить для JVM.

В Java все исключения делятся на два типа: контролируемые исключения (checked) и неконтролируемые исключения (unchecked), к которым относятся ошибки (Errors) и исключения времени выполнения (RuntimeExceptions, потомок класса Exception).

Контролируемые исключения представляют собой ошибки, которые можно и нужно обрабатывать в программе, к этому типу относятся все потомки класса Exception (но не RuntimeException).

3. Можно/нужно ли обрабатывать ошибки jvm?

Обрабатывать можно, но делать этого не стоит. Разработчику не предоставлены инструменты для обработки ошибок системы и виртуальной машины.

4. Какие существуют способы обработки исключений?

В Java есть пять ключевых слов для работы с исключениями:

  1. try — данное ключевое слово используется для отметки начала блока кода, который потенциально может привести к ошибке.
  2. catch — ключевое слово для отметки начала блока кода, предназначенного для перехвата и обработки исключений.
  3. finally — ключевое слово для отметки начала блока кода, которой является дополнительным. Этот блок помещается после последнего блока ‘catch’. Управление обычно передаётся в блок ‘finally’ в любом случае.
  4. throw — служит для генерации исключений.
  5. throws

Общий вид конструкции для «поимки» исключительной ситуации выглядит следующим образом:

Подробнее http://www.quizful.net/post/java-exceptions

5. О чем говорит ключевое слово throws?

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

6. В чем особенность блока finally? Всегда ли он исполняется?

Когда исключение передано, выполнение метода направляется по нелинейному пути. Это может стать источником проблем. Например, при входе метод открывает файл и закрывает при выходе. Чтобы закрытие файла не было пропущено из-за обработки исключения, был предложен механизм finally .

Ключевое слово finally создаёт блок кода, который будет выполнен после завершения блока try/catch , но перед кодом, следующим за ним. Блок будет выполнен, независимо от того, передано исключение или нет. Оператор finally не обязателен, однако каждый оператор try требует наличия либо catch , либо finally . Код в блоке finally будет выполнен всегда .

7. Может ли не быть ни одного блока catch при отлавливании исключений?

Такая запись допустима, если имеется связка try{} finally {}. Но смысла в такой записи не так много, всё же лучше иметь блок catch в котором будет обрабатываться необходимое исключение.

String x = "z"; try { x="234"; } finally { x = "Finally"; }

String x = "z" ;

try {

x = "234" ;

} finally {

x = "Finally" ;

8. Могли бы вы придумать ситуацию, когда блок finally не будет выполнен?

Блок finally выполняется не всегда, например в такой ситуации:

try { System.exit(0); } catch(Exception e) { e.printStackTrace(); } finally { }

try {

System . exit (0 ) ;

} catch (Exception e ) {

e . printStackTrace () ;

} finally { }

Здесь finally недостижим, так как происходит системный выход из программы. Общими словами: когда jvm умирает, ей не до finally (отсюда можете придумать другие примеры как убить jvm и ответить на вопрос в заголовке).

9. Может ли один блок catch отлавливать несколько исключений (с одной и разных веток наследований)?

В Java 7 стала доступна новая конструкция, с помощью которой можно перехватывать несколько исключений одним блоком catch:

try { ... } catch(IOException | SQLException ex) { logger.log(ex); throw ex; }

try {

. . .

} catch (IOException | SQLException ex ) {

logger . log (ex ) ;

throw ex ;

10. Что вы знаете об обрабатываемых и не обрабатываемых (checked/unchecked) исключениях?

Все исключительные ситуации делятся на «проверяемые» (checked) и «непроверяемые» (unchecked) (смотрите картинку в начале статьи). Это свойство присуще «корневищу» (Throwable, Error, Exception, RuntimeException) и передается по наследству. Никак не видимо в исходном коде класса исключения.
В дальнейших примерах просто учтите, что- Throwable и Exception и все их наследники (за исключением наследников Error-а и RuntimeException-а) - checked
- Error и RuntimeException и все их наследники - unchecked
checked exception = проверяемое исключение, проверяемое компилятором.

Тема достаточно обширная для того, чтобы уместить ее в одном ответе. К примеру, можно разобрать примеры Головача: http://habrahabr.ru/company/golovachcourses/blog/225585/

И еще с quizful.net

1. Checked исключения, это те, которые должны обрабатываться блоком catch или описываться в сигнатуре метода. Unchecked могут не обрабатываться и не быть описанными.
2. Unchecked исключения в Java — наследованные от RuntimeException, checked — от Exception (не включая unchecked).

Checked исключения отличаются от Unchecked исключения в Java, тем что:
1)Наличие\обработка Checked исключения проверяются на этапе компиляции . Наличие\обработка Unchecked исключения происходит на этапе выполнения .

11. В чем особенность RuntimeException?

public class RuntimeException extends Exception — базовый класс для ошибок во время выполнения. Относится к необрабатываемым исключениям (uncatched\unchecked). Как сказано в описании класса — это суперкласс, исключения которого могут быть выброшены во время нормальной работы JVM.

12. Как написать собственное (“пользовательское”) исключение? Какими мотивами вы будете руководствоваться при выборе типа исключения: checked/unchecked?

Необходимо унаследоваться от базового класса требуемого типа исключений (например от Exception или RuntimeException).

public class ExcClass extends Exception { private String someString; public ExcClass (String string) { this.someString = string; System.out.println("Exception ExcClass"); } public void myOwnExceptionMsg() { System.err.println("This is exception massage for string: " + someString); } } public class TestExc { public static void main(String args) { try { String s = "SomeString"; throw new ExcClass(s); } catch (ExcClass ex) { ex.myOwnExceptionMsg(); } } } //Вывод Exception ExcClass This is exception massage for string: SomeString

public class ExcClass extends Exception {

private String someString ;

public ExcClass (String string ) {

this . someString = string ;

System . out . println ("Exception ExcClass" ) ;

public void myOwnExceptionMsg () {

System . err . println ("This is exception massage for string: " + someString ) ;

public class TestExc {

try {

String s = "SomeString" ;

throw new ExcClass (s ) ;

} catch (ExcClass ex ) {

ex . myOwnExceptionMsg () ;

//Вывод

Exception ExcClass

This is exception massage for string : SomeString

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

13. Какой оператор позволяет принудительно выбросить исключение?

throw new Exception();

14. Есть ли дополнительные условия к методу, который потенциально может выбросить исключение?

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

Public void someMethod() throws Exception { }

public void someMethod () throws Exception {

15. Может ли метод main выбросить исключение во вне и если да, то где будет происходить обработка данного исключения?

Может и оно будет передано в виртуальную машину Java (JVM).

16. Если оператор return содержится и в блоке catch и в finally, какой из них “главнее”?

Вернется из блока finally.

Public static void main(String args) { String what = method(); System.out.println(what); } public static String method() { try { return "SomeString"; } finally { return "Finally message"; } } //Вывод Finally message

public static void main (String args ) {

String what = method () ;

System . out . println (what ) ;

public static String method () {

try {

return "SomeString" ;

} finally {

return "Finally message" ;

//Вывод

Finally message

17. Что вы знаете о OutOfMemoryError?

OutOfMemoryError выбрасывается, когда виртуальная машина Java не может выделить (разместить) объект из-за нехватки памяти, а сборщик мусора не может высвободить ещё.

Область памяти, занимаемая java процессом, состоит из нескольких частей. Тип OutOfMemoryError зависит от того, в какой из них не хватило места.

1. java.lang.OutOfMemoryError: Java heap space
Не хватает места в куче, а именно, в области памяти в которую помещаются объекты, создаваемые программно в вашем приложении. Размер задается параметрами -Xms и -Xmx. Если вы пытаетесь создать объект, а места в куче не осталось, то получаете эту ошибку. Обычно проблема кроется в утечке памяти, коих бывает великое множество, и интернет просто пестрит статьями на эту тему.

2. java.lang.OutOfMemoryError: PermGen space
Данная ошибка возникает при нехватке места в Permanent области, размер которой задается параметрами -XX:PermSize и -XX:MaxPermSize.

3. java.lang.OutOfMemoryError: GC overhead limit exceeded
Данная ошибка может возникнуть как при переполнении первой, так и второй областей. Связана она с тем, что памяти осталось мало и GC постоянно работает, пытаясь высвободить немного места. Данную ошибку можно отключить с помощью параметра -XX:-UseGCOverheadLimit, но, конечно же, её надо не отключать, а либо решать проблему утечки памяти, либо выделять больше объема, либо менять настройки GC.

4. java.lang.OutOfMemoryError: unable to create new native thread

Выбрасывается, когда нет возможности создать еще потоки.

Подробнее в статье http://habrahabr.ru/post/117274/

18. Что вы знаете о SQLException? К какому типу checked или unchecked оно относится, почему?

SQLException предоставляет информацию об ошибках доступа к базе данных или других ошибках связанных с работой с базами данных.

SQLException относится к checked исключениям, а значит проверяется на этапе компиляции.

Споры об этом типе исключения идут о том, что разработчику приходится постоянно обрабатывать это исключение в коде, хотя большая часть ошибок возникает во время выполнения программы, т.е., по мнению многих, лучше бы отнести его к unchecked runtime исключениям.

try { // make some SQL call(s) } catch {SQLException e) { // log the exception return; // and give up }

try {

// make some SQL call(s)

} catch { SQLException e ) {

// log the exception

return ; // and give up

Аргумент Joshua Bloch из Effective Java Second Edition такой: сделав SQLException проверяемым — это попытка заставить разработчиков обработать исключение и обернуть его в новом уровне абстракции.

19. Что такое Error? В каком случае используется Error. Приведите пример Error’а.

Ошибки (Errors) представляют собой более серьёзные проблемы, которые, согласно спецификации Java, не следует пытаться обрабатывать в собственной программе, поскольку они связаны с проблемами уровня JVM. Например, исключения такого рода возникают, если закончилась память, доступная виртуальной машине.

За примером посмотрите картинку иерархии исключений вначале статьи. Как пример — OutOfMemoryError.

20. Какая конструкция используется в Java для обработки исключений?

Можно использовать try-catch-finally и c 7й Java try-with-resources. Первый способ:

try{ //здесь код, который потенциально может привести к ошибке } catch(SomeException e){ //в скобках указывается класс конкретной ожидаемой ошибки //здесь описываются действия, направленные на обработку исключений } finally{ //выполняется в любом случае (блок finally не обязателен) }

Try с ресурсами:

Старый способ BufferedReader br = new BufferedReader(new FileReader(path)); try { return br.readLine(); } finally { if (br != null) { br.close(); } } JDK 7 try (BufferedReader br = new BufferedReader(new FileReader(path))) { return br.readLine(); }

Старыйспособ

BufferedReader br = new BufferedReader (new FileReader (path ) ) ;

try {

return br . readLine () ;

} finally {

if (br != null ) {

br . close () ;

JDK 7

try (BufferedReader br =

new BufferedReader (new FileReader (path ) ) ) {

return br . readLine () ;

Так же смотрите ответ к «Какие существуют способы обработки исключений?»

21. Предположим, есть блок try-finally. В блоке try возникло исключение и выполнение переместилось в блок finally. В блоке finally тоже возникло исключение. Какое из двух исключений “выпадет” из блока try-finally? Что случится со вторым исключением?

Ответ аналогичный случаю с двумя return — будет обработано в finally блоке. Если было выброшено два исключения — одно в try, второе в finally, то исключение в finally «проглотит» исключение выше (см. пример). Если до блока finally исключение было обработано, то мы можем получить информацию об исключении в блоке try и тем самым не потерять исключение, которое впоследствии может быть перезаписано в finally другим исключением.

public class TestExc { public static void main(String args) { Exception ex = twoExceptionsMethod(); System.out.println(ex.getClass()); String s = twoExceptionsMethod2(); System.out.println(s); } public static Exception twoExceptionsMethod() { try { return new IndexOutOfBoundsException(); } finally { return new NullPointerException(); } } public static String twoExceptionsMethod2() { try { throw new NullPointerException(); }catch (NullPointerException ex) { System.out.println(ex.getMessage()+ " catchBlock");; } finally { Exception ex2 = new Exception(); return ex2.getMessage() + "finallyBlock"; } } } //Вывод class java.lang.NullPointerException null catchBlock null finallyBlock

public class TestExc {

public static void main (String args ) {

Exception ex = twoExceptionsMethod () ;

System . out . println (ex . getClass () ) ;

В этой главе обсуждается используемый в Java механизм обработки исключений. Исключение в Java - это объект, который описывает исключительное состояние, воз­никшее в каком-либо участке программного кода. Когда возникает ис­ключительное состояние, создается объект класса Exception. Этот объект пересылается в метод, обрабатывающий данный тип исключительной ситуации. Исключения могут возбуждаться и «вруч­ную» для того, чтобы сообщить о некоторых нештатных ситуациях.

Основы

К механизму обработки исключений в Java имеют отношение 5 клю­чевых слов: - try , catch , throw , throws и finally . Схема работы этого механизма следующая. Вы пытаетесь (try) выполнить блок кода, и если при этом возникает ошибка, система возбуждает (throw) исключение, ко­торое в зависимости от его типа вы можете перехватить (catch) или пере­дать умалчиваемому (finally) обработчику.

Ниже приведена общая форма блока обработки исключений.

try {

// блок кода }

catch (ТипИсключения1 е) {

// обработчик исключений типа ТипИсключения1 }

catch (ТипИсключения2 е) {

// обработчик исключений типа ТипИсключения2

throw(e)// повторное возбуждение исключения }

finally {

}

ЗАМЕЧАНИЕ

В языке Delphi вместо ключевого слова catch используется except.

Типы исключений

В вершине иерархии исключений стоит класс Throwable. Каждый из типов исключений является подклассом класса Throwable. Два непосредственных наследника класса Throwable делят иерархию подклассов исключений на две различные ветви. Один из них - класс Ехception - используется для описания исключительных ситуации, кото­рые должны перехватываться программным кодом пользователя. Другая ветвь дерева подклассов Throwable - класс Error, который предназначен для описания исклю­чительных ситуаций, которые при обычных условиях не должны перехватываться в пользовательской программе.

Неперехваченные исключения

Объекты-исключения автоматически создаются исполняющей средой Java в результате возникновения определенных исключительных состо­яний. Например, очередная наша программа содержит выражение, при вычислении которого возникает деление на нуль.

class Exc 0 {

int d = 0;

int a = 42 / d;

} }

Вот вывод, полученный при запуске нашего примера.

С:\> java Exc0

at Exc0.main(Exc0.java:4)

О братите внимание на тот факт что типом возбужденного исклю­чения был не Exception и не Throwable. Это подкласс класса Exception, а именно: ArithmeticException, поясняющий, какая ошибка возникла при выполнении программы. Вот другая версия того же класса, в кото­рой возникает та же исключительная ситуация, но на этот раз не в про­граммном коде метода main.

class Exc1 {

static void subroutine() {

int d = 0;

int a = 10 / d;

}

public static void main(String args) {

Exc1.subroutine();

} }

Вывод этой программы показывает, как обработчик исключений ис­полняющей системы Java выводит содержимое всего стека вызовов.

С:\> java Exc1

java.lang.ArithmeticException: / by zero

at Exc1.subroutine(Exc1.java:4)

at Exc1.main(Exc1.java:7)

try и catch

Для задания блока программного кода, который требуется защитить от исключений, исполь­зуется ключевое слово try. Сразу же после try-блока помещается блок catch, задающий тип исключения которое вы хотите обрабатывать.

class Exc2 {

public static void main(String args) {

try {

int d = 0;

int a = 42 / d;

}

System.out.println("division by zero");

}

} }

Целью большинства хорошо сконструированных catch-разделов долж­на быть обработка возникшей исключительной ситуации и приведение переменных программы в некоторое разумное состояние - такое, чтобы программу можно было продолжить так, будто никакой ошибки и не было (в нашем примере выводится предупреждение – division by zero) .

Несколько разделов catch

В некоторых случаях один и тот же блок программного кода может воз­буждать исключения различных типов. Для того, чтобы обрабатывать по­добные ситуации, Java позволяет использовать любое количество catch-разделов для try-блока. Наиболее специализированные классы исключений должны идти первыми, поскольку ни один подкласс не будет достигнут, если поставить его после суперкласса. Следующая про­грамма перехватывает два различных типа исключений, причем за этими двумя специализированными обработчиками следует раздел catch общего назначения, перехватывающий все подклассы класса Throwable.

class MultiCatch {

public static void main(String args) {

try {

int a = args.length;

int b = 42 / a;

int c = { 1 };

c = 99;

}

catch (ArithmeticException e) {

}

}

} }

Этот пример, запущенный без параметров, вызывает возбуждение ис­ключительной ситуации деления на нуль. Если же мы зададим в командной строке один или несколько параметров, тем самым установив а в значение боль­ше нуля, наш пример переживет оператор деления, но в следующем опе­раторе будет возбуждено исключение выхода индекса за границы масси­ва ArrayIndexOutOf Bounds. Ниже приведены результаты работы этой программы, за­пущенной и тем и другим способом.

С:\> java MultiCatch

а = 0

div by 0: java.lang.ArithmeticException: / by zero

C:\> java MultiCatch 1

a = 1

array index oob: java.lang.ArrayIndexOutOfBoundsException: 42

Вложенные операторы try

Операторы try можно вкладывать друг в друга аналогично тому, как можно создавать вложенные области видимости переменных. Если у оператора try низкого уровня нет раздела catch, соответствующего возбужденному исключению, стек будет развернут на одну ступень выше, и в поисках подходящего обработчика будут прове­рены разделы catch внешнего оператора try. Вот пример, в котором два оператора try вложены друг в друга посредством вызова метода.

class MultiNest {

static void procedure() {

try {

int c = { 1 };

c = 99;

}

catch(ArrayIndexOutOfBoundsException e) {

System.out.println("array index oob: " + e);

} }

public static void main(String args) {

try {

int a = args.length();

System.out.println("a = " + a);

int b = 42 / a;

procedure();

}

catch (ArithmeticException e) {

System.out.println("div by 0: " + e);

}

} }

throw

Оператор throw используется для возбуждения исключения «вруч­ную». Для того, чтобы сделать это, нужно иметь объект подкласса клас­са Throwable, который можно либо получить как параметр оператора catch, либо создать с помощью оператора new. Ниже приведена общая форма оператора throw.

throw ОбъектТипаThrowable;

При достижении этого оператора нормальное выполнение кода немед­ленно прекращается, так что следующий за ним оператор не выполня­ется. Ближайший окружающий блок try проверяется на наличие соот­ветствующего возбужденному исключению обработчика catch. Если такой отыщется, управление передается ему. Если нет, проверяется следующий из вложенных операторов try, и так до тех пор пока либо не будет най­ден подходящий раздел catch, либо обработчик исключений исполняю­щей системы Java не остановит программу, выведя при этом состояние стека вызовов. Ниже приведен пример, в котором сначала создается объект-исключение, затем оператор throw возбуждает исключительную ситуацию, после чего то же исключение возбуждается повторно - на этот раз уже кодом перехватившего его в первый раз раздела catch.

class ThrowDemo {

static void demoproc() {

try {

throw new NullPointerException("demo");

}

catch (NullPointerException e) {

System.out.println("caught inside demoproc");

throw e;

} }

public static void main(String args) {

try {

demoproc();

}

catch(NulPointerException e) {

System.out.println("recaught: " + e);

}

} }

В этом примере обработка исключения проводится в два приема. Метод main создает контекст для исключения и вызывает demoproc. Метод demoproc также устанавливает контекст для обработки исключе­ния, создает новый объект класса NullPointerException и с помощью опе­ратора throw возбуждает это исключение. Исключение перехватывается в следующей строке внутри метода demoproc, причем объект-исключение доступен коду обработчика через параметр e. Код обработчика выводит сообщение о том, что возбуждено исключение, а затем снова возбуждает его с помощью оператора throw, в результате чего оно передается обра­ботчику исключений в методе main. Ниже приведен результат, получен­ный при запуске этого примера.

С:\> java ThrowDemo

caught inside demoproc

recaught: java.lang.NullPointerException: demo

throws

Если метод способен возбуждать исключения, которые он сам не об­рабатывает, он должен объявить о таком поведении, чтобы вызывающие методы могли защитить себя от этих исключений. Для задания списка исключений, которые могут возбуждаться методом, используется ключе­вое слово throws . Если метод в явном виде (т.е. с помощью оператора throw) возбуждает исключе­ние соответствующего класса, тип класса исключений должен быть ука­зан в операторе throws в объявлении этого метода. С учетом этого наш прежний синтаксис определения метода должен быть расширен следую­щим образом:

тип имя_метода(список аргументов) throws список_исключений {}

Ниже приведен пример программы, в которой метод procedure пыта­ется возбудить исключение, не обеспечивая ни программного кода для его перехвата, ни объявления этого исключения в заголовке метода. Такой программный код не будет оттранслирован.

class ThrowsDemo1 {

static void procedure() {

System.out.println("inside procedure");

}

public static void main(String args) {

procedure();

} }

Для того, чтобы мы смогли оттранслировать этот пример, нам при­дется сообщить транслятору, что procedure может возбуждать исключе­ния типа IllegalAccessException и в методе main добавить код для обработки этого типа исключений:

class ThrowsDemo {

static void procedure() throws IllegalAccessException {

System.out.println(" inside procedure");

throw new IllegalAccessException("demo");

}

public static void main(String args) {

try {

procedure();

}

catch (IllegalAccessException e) {

System.out.println("caught " + e);

}

} }

Ниже приведен результат выполнения этой программы.

С:\> java ThrowsDemo

inside procedure

caught java.lang.IllegalAccessException: demo

finally

Иногда требуется гарантировать, что определенный участок кода будет выпол­няться независимо от того, какие исключения были возбуждены и пере­хвачены. Для создания такого участка кода используется ключевое слово finally. Даже в тех случаях, когда в методе нет соответствующего воз­бужденному исключению раздела catch, блок finally будет выполнен до того, как управление перейдет к операторам, следующим за разделом try. У каждого раздела try должен быть по крайней мере или один раз­дел catch или блок finally. Блок finally очень удобе н для закрытия файлов и освобождения любых других ресурсов, захваченных для времен­ного использования в начале выполнения метода. Ниже приведен пример класса сдвумяметодами,завершение которых происходит по разным причинам, нов обоихперед выходом выполняется код раздела finally.

class FinallyDemo {

static void procA() {

try {

System.out.println("inside procA");

throw new RuntimeException("demo");

}

finally {

System.out.println("procA"s finally");

} }

static void procB() {

try {

System.out.println("inside procB");

return;

}

finally {

System.out.println("procB"s finally");

} }

public static void main(String args) {

try {

procA();

}

catch (Exception e) {}

procB();

} }

В этом примере в методе procA из-за возбуждения исключения про­исходит преждевременный выход из блока try, но по пути «наружу» вы­полняется раздел finally. Другой метод procB завершает работу выпол­нением стоящего в try-блоке оператора return, но и при этом перед выходом из метода выполняется программный код блока finally. Ниже приведен результат, полученный при выполнении этой программы.

С:\> java FinallyDemo

inside procA

procA"s finally

inside procB

procB"s finally

Подклассы Exception

Только подклассы класса Throwable могут быть возбуждены или пере­хвачены. Простые типы - int, char и т.п., а также классы, не являю­щиеся подклассами Throwable, например, String и Object, использоваться в качестве исключений не могут. Наиболее общий путь для использова­ния исключений - создание своих собственных подклассов класса Ex­ception. Ниже приведена программа, в которой объявлен новый подкласс класса Exception.

class MyException extends Exception {

private int detail;

MyException(int a) {

detail = a:

}

public String toString() {

return "MyException[" + detail + "]";

}

}

class ExceptionDemo {

static void compute(int a) throws MyException {

System.out.println("called computer + a + ").");

if (a > 10)

throw new MyException(a);

System.out.println("normal exit.");

}

public static void main(String args) {

try {

compute(1);

compute(20);

}

catch (MyException e) {

System.out.println("caught" + e);

}

} }

Этот пример довольно сложен. В нем сделано объявление подкласса MyException класса Exception. У этого подкласса есть специальный кон­структор, который записывает в переменную объекта целочисленное значение, и совмещенный метод toString, выводящий значение, хранящееся в объекте-исключении. Класс ExceptionDemo определяет метод compute, который возбуждает исключение типа MyExcepton. Простая логика метода compute возбуждает исключение в том случае, когда значение пара-ветра метода больше 10. Метод main в защищенном блоке вызывает метод compute сначала с допустимым значением, а затем - с недопус­тимым (больше 10), что позволяет продемонстрировать работу при обоих путях выполнения кода. Ниже приведен результат выполнения програм­мы.

С:\> java ExceptionDemo

called compute(1).

normal exit.

called compute(20).

caught MyException

Заключительное резюме

Обработка исключений предоставляет исключительно мощный меха­низм для управления сложными программами. Try, throw, catch дают вам простой и ясный путь для встраивания обработки ошибок и прочих нештатных ситуаций в программную логи­ку. Если вы научитесь должным об­разом использовать рассмотренные в данной главе механизмы, это при­даст вашим классам профессиональный вид, и любые будущие пользователи вашего программного кода, несомненно, оценят это.

Последнее обновление: 30.10.2015

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

В языке Java предусмотрены специальные средства для обработки подобных ситуаций. Одним из таких средств является конструкция try...catch...finally . При возникновении исключения в блоке try управление переходит в блок catch, который может обработать данное исключение. Если такого блока не найдено, то пользователю отображается сообщение о необработанном исключении, а дальнейшее выполнение программы останавливается. И чтобы подобной остановки не произошло, и надо использовать блок try..catch. Например:

Int numbers = new int; numbers=45; System.out.println(numbers);

Так как у нас массив numbers может содержать только 3 элемента, то при выполнении инструкции numbers=45 консоль отобразит исключение, и выполнение программы будет завершено. Теперь попробуем обработать это исключение:

Try{ int numbers = new int; numbers=45; System.out.println(numbers); } catch(Exception ex){ ex.printStackTrace(); } System.out.println("Программа завершена");

При использовании блока try...catch вначале выполняются все инструкции между операторами try и catch. Если в блоке try вдруг возникает исключение, то обычный порядок выполнения останавливается и переходит к инструкции сatch. Поэтому когда выполнение программы дойдет до строки numbers=45; , программа остановится и перейдет к блоку catch

Выражение catch имеет следующий синтаксис: catch (тип_исключения имя_переменной) . В данном случае объявляется переменная ex , которая имеет тип Exception . Но если возникшее исключение не является исключением типа, указанного в инструкции сatch, то оно не обрабатывается, а программа просто зависает или выбрасывает сообщение об ошибке.

Но так как тип Exception является базовым классом для всех исключений, то выражение catch (Exception ex) будет обрабатывать практически все исключения. Обработка же исключения в данном случае сводится к выводу на консоль стека трассировки ошибки с помощью метода printStackTrace() , определенного в классе Exception.

После завершения выполнения блока catch программа продолжает свою работу, выполняя все остальные инструкции после блока catch.

Конструкция try..catch также может иметь блок finally . Однако этот блок необязательный, и его можно при обработке исключений опускать. Блок finally выполняется в любом случае, возникло ли исключение в блоке try или нет:

Try{ int numbers = new int; numbers=45; System.out.println(numbers); } catch(Exception ex){ ex.printStackTrace(); } finally{ System.out.println("Блок finally"); } System.out.println("Программа завершена");

Обработка нескольких исключений

В Java имеется множество различных типов исключений, и мы можем разграничить их обработку, включив дополнительные блоки catch:

Int numbers = new int; try{ numbers=45; numbers=Integer.parseInt("gfd"); } catch(ArrayIndexOutOfBoundsException ex){ System.out.println("Выход за пределы массива"); } catch(NumberFormatException ex){ System.out.println("Ошибка преобразования из строки в число"); }

Если у нас возникает исключение определенного типа, то оно переходит к соответствующему блоку catch.

Оператор throw

Чтобы сообщить о выполнении исключительных ситуаций в программе, можно использовать оператор throw . То есть с помощью этого оператора мы сами можем создать исключение и вызвать его в процессе выполнения. Например, в нашей программе происходит ввод числа, и мы хотим, чтобы, если число больше 30, то возникало исключение:

Package firstapp; import java.util.Scanner; public class FirstApp { public static void main(String args) { try{ Scanner in = new Scanner(System.in); int x = in.nextInt(); if(x>=30){ throw new Exception("Число х должно быть меньше 30"); } } catch(Exception ex){ System.out.println(ex.getMessage()); } System.out.println("Программа завершена"); } }

Здесь для создания объекта исключения используется конструктор класса Exception, в который передается сообщение об исключении. И если число х окажется больше 29, то будет выброшено исключение и управление перейдет к блоку catch.

В блоке catch мы можем получить сообщение об исключении с помощью метода getMessage() .

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

В java исключением называется любая ошибка, которая возникает в ходе выполнения программы. Это может быть несоответствие типов данных, деление на ноль, обрыв связи с сервером и многое другое. Операции по их поиску и предотвращению называются обработкой исключений.

Иерархия

Прежде чем мы перейдём к практике, давайте познакомимся с видами исключений Джава и их иерархией. В основе всего лежит класс Throwable. Все возможные конфликты кода с машиной и пользователем описаны здесь. Для удобства обработки и чтения класс Throwable имеет подклассы Error и Exception. Error – критические ошибки, которые не обязательно происходят по вине пользователя, обработать их невозможно. Exception – собственно конфликты нашей программы, которые необходимо отлавливать.

Взгляните на упрощённую схему иерархии исключений java:

Как видно, блоки делятся на «два лагеря» по цветам - проверяемые и непроверяемые java исключения. Данная классификация показывает, как их воспринимает компилятор: проверяемые – учитывает, непроверяемые – игнорирует. К первому относится Exception в полном составе, кроме RuntimeException. Все остальные классы исключений – непроверяемые компилятором.

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

Создание обработчика

Для обработки исключений java используются следующие операторы: try, catch, finally, throw, throws. Первые три - стандартная структура вашего блока. По шагам:

  1. Оператор или часть кода, в которой вам надо отыскать ошибку, помещается в блок try.
  2. Далее в блоке catch вы указываете, что за исключение надо ловить и как его обрабатывать.
  3. В блоке finally набор обязательных действий при возникновении ошибки. Обычно это запись данных, закрытие ресурсов и пр. Блок исполняется всегда, вне зависимости от срабатывания catch.

Рассмотрим структуру на примере Джава исключения:

try {

}
catch (тип_исключения объект_исключения) {
// код обработки
}
finally {

}

Если вы хотите обработать несколько исключений – просто создайте ещё один блок catch.

try {
// код, где мы хотим отследить ошибку
}
catch (тип_исключения_1 объект_исключения_1) {
// код обработки
}
catch (тип_исключения_2 объект_исключения_2) {
// код обработки
}
finally {
// что нужно выполнить после завершения блока try
}

С помощью оператора throw вы можете создавать исключения:

throw экземпляр_Throwable

На практике это выглядит так:

Student stud1;

if(stud1 == null){

}
}

Включим оператор throw в наш стандартный пример с try-catch:

public void onClick(View view) {
if (stud1 == null) {
try {
throw new NullPointerException("Студента не существует");
} catch (NullPointerException e) {
Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
}
}
}

Как только обработка дойдёт до оператора throw, дальнейшее выполнение кода будет прекращено. Обработчик рассмотрит ближайший блок try-catch на требуемое исключение, потом следующий и так до конца кода. В случае, если вызвать ява исключение неоткуда – обработчик остановит программу.

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

тип имя_метода(список_параметров) throws список_исключений {
// код метода
}

Несколько исключений в списке необходимо перечислить через запятую. Воспользовавшись такой конструкцией, вы сообщите всем вызывающим методам о необходимости учитывать исключения.

Операторы try можно вкладывать друг в друга. При этом если вложенный обработчик не имеет своего блока catch, он осуществляет его поиск в родительском операторе. Если и там нет – блок обрабатывается системой.

Готовые и новые исключения

  • ArithmeticException - ошибки вычислений.
  • NullPointerException - ссылка на пустое место.
  • NegativeArraySizeException - массив отрицательной размерности.
  • ArrayStoreException - присвоение элементу массива неправильного типа.
  • NumberFormatException - невозможно преобразовать строку в число.
  • IllegalArgumentException - неправильный аргумент при вызове метода.
  • UnsupportedOperationException - указанной операции не существует.
  • TypeNotPresentException - указанного типа не существует.

Все указанные типы java исключений содержатся в классе RuntimeException, а значит, их не надо указывать в блоке throws.

Естественно, система не может содержать всевозможные исключения. Некоторые придётся создавать самостоятельно. Для того, чтобы создать собственное java исключение, вам необходимо унаследовать собственный класс от Exception и переопределить требуемые методы класса Throwable. Или унаследоваться от наиболее близкого по смыслу типа. Рассмотрим на примере программы под android создание java исключения:

package geekbrains.exception;

Import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;

Public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}

Public void testMethod() throws StudentException {
System.out.println("Возбуждаем StudentException из метода testMethod()");
throw new StudentException(); // конструктор по умолчанию
}

Public void testMethod2() throws StudentException {
System.out.println("Возбуждаем StudentException из метода testMethod2()");
throw new StudentException("Создано во втором методе");
}

Public void onClick(View view) {
try {
testMethod();

e.printStackTrace();
System.out.println("Исключение перехвачено");
}

Try {
testMethod2();
} catch (StudentException e) {
e.printStackTrace();
}
}

Class StudentException extends Exception {
StudentException() {
}

StudentException(String msg) {
super(msg);
}
}
}

Обработка исключений – основа безопасного и качественного кода. С их помощью вы можете управлять действиями пользователя, ходом выполнения программы или добавить вариативности коду.