Что такое исключение в Java?

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

Иерархия исключений в Java:

В иерархии классов исключений Java класс наверху — это класс Throwable, который является прямым подклассом класса Object. Throwable имеет два прямых подкласса Exception и Error, у которых снова есть соответствующие подклассы. На приведенной ниже диаграмме показаны стандартные классы исключений и ошибок, определенные в Java, организованные в иерархию исключений Java:

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

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

В java доступны два типа исключений.

1. Проверенное исключение:

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

2. Непроверенное исключение:

  • Исключение, которое не проверяется компилятором, называется Непроверяемое исключение.
  • Это исключение возникает во время выполнения программы. Все исключения Runtime и его дочерние классы, Error и его дочерние классы подпадают под исключения Unchecked.
  • Пример:

Зачем нам нужна обработка исключений?

Чтобы определить какой-то альтернативный способ продолжить остальную часть программы в обычном режиме, то есть для корректного завершения программы, обработка исключений играет важную роль. Исключения вызваны программным кодом программиста и могут быть обработаны путем реализации определенного кода.

Как обрабатывать исключения в Java?

В Java есть два способа обработки исключений.

1. Обработка исключений по умолчанию в Java с помощью JVM:

i) Для каждого потока JVM создаст один отдельный стек во время выполнения.

ii) Для каждого вызова метода, выполняемого этим потоком, одна запись будет храниться в соответствующем стеке. Каждая запись называется записью активации кадра стека.

iii) JVM начнет выполняться с вершины стека. Если метод имеет исключение, JVM проверяет, обрабатывается ли это исключение методом или нет, если нет, JVM аварийно завершает этот метод и удаляет (операция всплывающего окна стека) запись активации из кадра стека.

iv) Теперь JVM проверяет вызывающий метод, обработал ли он исключение или нет. Если нет, то он снова завершает и вызывающий метод. Этот процесс продолжается, и если функция main() также не обработала исключение, то JVM завершает работу и удаляет запись main() из стека.

v) Ответственность за обработку исключений теперь возложена на JVM, где JVM обрабатывает его с помощью обработчика исключений по умолчанию, который выводит сообщение об исключении на консоль в формате ExcepionInThreadMain.Name для exception.atlineNumberMethodName() и завершает работу программы.

2. Обработка исключений программистом с использованием кода:

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

i) блок try-catch:

Блок try-catch в java может использоваться для обработки рискованного кода и может использоваться как для проверенных, так и для непроверенных исключений. Давайте посмотрим на это:

try
{
statement 1;
statement 2;
statement 3;
}
catch (xxxx e){
statement 4;
}
statement 5;
Case 1: If There is No Exception: Statement 1, 2, 3, 5, no abnormal termination.
Case 2: If an exception occurs at statement 2 and corresponding catch block matched: Executes statement 1, 4, 5, no abnormal termination.
Case 3: If an exception occurs at statement 2 and corresponding catch block Not matched: Executes statement 1, Abnormal Termination.
Case 4: If an exception occurs at Statement 2 and Statement 4: Executes Statement 1, then abnormal termination
Case 5: If an exception occurs at Statement 5: Executes Statement 1,2,3 then abnormal termination because cache doesn’t handle code outside try block.

Способы вывода исключения на консоль:

Класс Throwable содержит следующие 3 метода для печати исключения.

1. e.printStackTrace
2. e.toString: System.out.println( e.toString());
то же, что и System.out.println(e);
3. System.out.println(e.getMessage(););

ii) попробуйте использовать несколько блоков catch:

  • В случае попытки с несколькими блоками catch мы обязательно должны перевести исключение дочернего класса в родительское исключение, как показано ниже в примере 2, иначе мы получим ошибку времени компиляции, как показано в примере 1.
try with multiple catch block example 1:
public void DemoTryMultiCache1() {
int i , j ;
j = 0;
try {
i = 90 / j; // can cause exception (Expected ArithmeticException)
} 
catch (Exception e ) {
System. out .println(e );
} 
catch (ArithmeticException e ) { // Compiletime Error: Unreachable catch block for ArithmeticException. It is already handled by the catch block for Exception
System. out .println(e .getMessage());
}
}

Правильный способ обработки try с несколькими блоками catch:

try with multiple catch block example 2:
public void DemoTryMultiCache() {
int i , j ;
j = 0;
try {
i = 90 / j;  // can cause exception (ExpectedArithmeticException)
} catch (ArithmeticException e ) { // output: java.lang.ArithmeticException: divide by zero
System. out.println(e );
} catch (ArrayIndexOutOfBoundsException e ) {
System. out.println(e .getMessage());
} catch (Exception e ) {
System. out.println(e );
}
}

iii) Окончательный блок:

Код блока finally всегда выполняется независимо от того, произошло исключение или нет, обработано оно или нет. Этот блок особенно может использоваться для поддержки всего кода очистки, такого как закрытие соединения с БД и т. д.

Finally vs Return:после выполнения блока try блок finally выполняется, даже если оператор return доступен внутри блока try. finally-block получает более высокий приоритет, чем оператор return. В случае, если все блоки try, cache и finally возвращают какое-то значение, тогда возврат блока finally имеет приоритет.

/**
* Demo: return statement in all try, cache, finally block.
* Finally block return statement takes priority.
*/
@SuppressWarnings(“finally” )
public int DemoReturn() {
try {
int i = 90 / 9;
return i ;
} catch (NullPointerException e ) {
return 92;
} finally {
return 99; // o/p: 99
}
}

Наконец по сравнению с System.exit(0):JVM получает выход, когда System.exit(0); код выполняется. Если в блоке try System.exit(0); используется, тогда блок finally не будет выполнен.

/**
* Finally vs System.exit(0); JVM gets normally terminated when System.exit(0);
* executes. Hence, finally block doesn’t gets executed. Note: System.exit(0);
* // if we use 0 : Normal termination, For non-zero: abnormal termination o/p:5 
*Finally block doesn’t gets executed.
*/
public void DemoFinallyBlockNotExecute() {
try {
int i = 10 / 2;
System.out.println(i);
System.exit(0);
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println(“Regardless exception is handled in cache block or not, Finally block will get executed.”);
}
}

Поток управления в блоке try-catch-finally:

try
{
statement 1;
statement 2;
statement 3;
}
catch (xxxx e){
statement 4;
}
finally{
statement 5;
}
statement 6;
Case 1: If There is No Exception: Statement 1, 2, 3, 5, 6 no abnormal termination.
Case 2: If an exception occurs at statement 2 and corresponding catch block matched: Executes statement 1, 4, 5, 6 no abnormal termination.
Case 3: If an exception occurs at statement 2 and corresponding catch block Not matched: Executes statement 1, 5, Abnormal Termination.
Case 4: If an exception occurs at Statement 2 and Statement 4: Executes Statement 1,5 then abnormal termination.
Case 5: If an exception occurs at Statement 5, or statement 6: Abnormal termination because cache doesn’t handle code outside try block.

Поток управления во вложенном блоке try-catch-finally:

/**
* Nested Try catch finally Block:
*
*/
public void DemoNestedTryCatchFinallyBlock() {
try {
System. out.println(“Statement 1” );
System. out.println(“Statement 2” );
System. out.println(“Statement 3” );
try {
System. out.println(“Statement 4” );
System. out.println(“Statement 5” );
System. out.println(“Statement 6” );
} catch(Exception e ) {
System. out.println(“Statement 7” );
}
finally {
System. out.println(“Statement 8” );
}
System. out.println(“Statement 9” );
} catch (Exception e ) {
System. out.println(“Statement 10” );
} finally {
System. out.println(“Statement 11” );
}
System. out.println(“Statement 12” );
}
Case 1: If There is No Exception: Statement 1, 2, 3,4 5, 6,8,9,11,12 no abnormal termination.
Case 2: If an exception occurs at statement 2 and corresponding catch block matched: Executes statement 1, 10,11,12, no abnormal termination.
Case 3: If an exception occurs at statement 2 and corresponding catch block Not matched: Executes statement 1, 11, Abnormal Termination.
Case 4: If an exception occurs at Statement 5 and corresponding inner catch block matched: Executes statement 1,2,3,4,7,8,9,11,12, no abnormal termination.
Case 5: If an exception occurs at Statement 5 and corresponding inner catch block Not matched but outer catch block matched: Executes statement 1,2,3,4,8,10,11,12, no abnormal termination.
Case 6: If an exception occurs at Statement 5 and both inner catch block and outer catch block Not matched: Executes Statement 1,2,3,4,8,11 then abnormal termination.
Case 7: If an exception occurs at Statement 5 and 7 and corresponding catch block matched: Executes Statement 1,2,3,4,8,10,11,12, no abnormal termination.
Case 8: If an exception occurs at Statement 5 and 7 and corresponding catch block not matched: Executes Statement 1,2,3,4,8,11 and then abnormal termination.
Case 9: If an exception occurs at Statement 8 and corresponding catch block matched: Executes Statement 1,2,3,4,5,6,10,11,12 and then no abnormal termination.
Case 10: If an exception occurs at Statement 8 and corresponding catch block not matched: Executes Statement 1,2,3,4,5,6,11 and then abnormal termination.
Case 11: If an exception occurs at Statement 9 and corresponding catch block matched: Executes Statement 1,2,3,4,5,6,8,10, 11,12 and then no abnormal termination.
Case 12: If an exception occurs at Statement 9 and corresponding catch block not matched: Executes Statement 1,2,3,4,5,6,8, 11 and then abnormal termination.
Case 13: If an exception occurs at Statement 9 and corresponding catch block not matched: Executes Statement 1,2,3,4,5,6,8, 11 and then abnormal termination.
Case 14: If an exception occurs at Statement 2 and 10: Executes Statement 1,11 and then abnormal termination.
Case 15: If an exception occurs at Statement 11: Executes Statement 1,2,3,4,5,6,8,9 and then abnormal termination because cache doesn’t handle code outside try block.
Case 15: If an exception occurs at Statement 12: Executes Statement 1,2,3,4,5,6,8,9,11 and then abnormal termination because cache doesn’t handle code outside try block.

iv) ключевое слово throw:

Чтобы создать настроенное исключение и передать его JVM, мы используем ключевое слово throw. Ключевое слово throw настоятельно рекомендуется для непроверенных исключений.

  • Синтаксис: throw new ExceptionName ("Message");
  • Пример: throw new ArithmeticException("Вы делите число на ноль");

  • После оператора throw мы не можем принимать никакие другие операторы напрямую.

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

  • Программист может разрешить вышеуказанное, расширив любой подкласс класса Throwable (концепция наследования), как показано ниже:

v) бросает ключевое слово:

  • Мы можем использовать ключевое слово throws, чтобы делегировать ответственность за обработку исключений JVM или любому другому методу.
  • Это необходимо только для продолжения работы компилятора, и его использование не предотвращает аварийное завершение программы, поэтому его можно использовать только в случае проверенного исключения.
  • ключевое слово throws всегда мы пишем с сигнатурой метода.
  • Как и ключевое слово throw, мы можем использовать ключевое слово throws только для подклассов класса Throwable.

Давайте обобщим концепцию пяти ключевых слов (try, catch, finally, throw, throws) для обработки исключений, которые мы изучили до сих пор:

Обработка исключений — одна из самых важных тем в Java как для программирования, так и для интервью с Java. Я надеюсь, что эта статья помогла вам получить более четкое представление об обработке исключений в Java. Пожалуйста, не стесняйтесь оставлять отзывы о вышеизложенном и подписывайтесь на другие статьи, связанные с этим и многим другим!