Файл: Что такое исключение Для чего они нужны.docx

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 05.02.2024

Просмотров: 18

Скачиваний: 0

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

Что такое исключение? Для чего они нужны? 

Исключения в программировании (exceptions) — это механизм, который позволяет программе обрабатывать нетипичную ситуацию и при этом не прекращать работу. Благодаря этому механизму разработчик может описать в коде реакцию программы на такие ситуации.

Механизм обработки исключений может понадобиться любому разработчику. Если не отслеживать исключительные ситуации, может возникнуть незаметная ошибка, которая нарушит работу всего кода, или программа может «зависнуть» либо «упасть» — потому что сложный момент не был обработан как надо.

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

Расскажи про иерархию исключений?



В Java все исключения наследуются от класса Throwable, который является корневым классом иерархии исключений в Java. Класс Throwable имеет два основных подкласса: Error и Exception.

Класс Error представляет ошибки, возникающие внутри виртуальной машины Java (JVM) и не подлежащие обработке. Некоторые из распространенных ошибок, наследующихся от класса Error, включают OutOfMemoryError (когда не хватает памяти для выполнения программы) и StackOverflowError (когда слишком много вызовов методов приводят к переполнению стека).

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

Ниже класса Exception располагаются классы RuntimeException и Error, которые наследуются от класса Throwable, но не являются подклассами класса Exception.

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


Создание исключения

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

Обработка исключения

Создание блоков кода, для которых мы предусматриваем обработку исключений в Java, производится в программе с помощью конструкций try{}catch, try{}catch{}finally, try{}finally{}.



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

После выполнения блока catch управление передается в необязательный блок finally.

В случае, если подходящий блок catch не найден, JVM останавливает выполнение программы, и выводит стек вызовов методов – stack trace, выполнив перед этим код блока finally при его наличии.

В чём разница между проверяемыми исключениями и непроверяемыми? В чём разница с точки зрения синтаксиса и идеологическая при использовании?

В Java существует два типа исключений: проверяемые (checked) и непроверяемые (unchecked) исключения.

Проверяемые исключения - это исключения, которые должны быть обработаны или переданы в вызывающий метод. Компилятор Java требует, чтобы методы, которые могут сгенерировать проверяемое исключение, явно объявляли это в списке throws. Примерами проверяемых исключений являются FileNotFoundException и IOException.

Непроверяемые исключения - это исключения, которые не обязательно должны быть обработаны или объявлены в списке throws. Эти исключения обычно свидетельствуют об ошибках в программе или невозможности продолжить выполнение программы. Примеры непроверяемых исключений: NullPointerException, ArrayIndexOutOfBoundsException, IllegalArgumentException.

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

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


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

Можно ли обработать непроверяемое исключение?

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

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

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

try {

int[ ] arr = {1, 2, 3};

System.out.println(arr[3]); // Вызовет ArrayIndexOutOfBoundsException

} catch (ArrayIndexOutOfBoundsException e) {

System.out.println("Выход за пределы массива");

Здесь мы попытались обратиться к элементу массива, который не существует, и возникло исключение ArrayIndexOutOfBoundsException. Однако блок catch перехватил это исключение и вывел сообщение об ошибке вместо аварийного завершения программы.

Нужно ли ловить Error исключения?

В Java, классы Error и его подклассы, такие как OutOfMemoryError (приложение пытается выделить больше памяти, чем доступно в системе) и StackOverflowError (бесконечная рекурсия), предназначены для обозначения серьезных, неустранимых ошибок, которые обычно возникают в работающей программе и указывают на серьезные проблемы среды выполнения. В таких ситуациях приложение, как правило, не может справиться с этими ошибками и должно быть завершено.

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

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


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

Как бросить исключение? Можно ли бросить НЕ новое исключение?

Да, в Java можно бросить не новое исключение. Это делается с помощью ключевого слова throw. Оно принимает любой экземпляр Throwable (или его производных) - это суперкласс для всех типов исключений.

Например, следующая строка кода бросает некоторое уже существующее исключение:

throw new IllegalArgumentException("Invalid argument");

Где возможно вызывать исключения? 

  • В любом месте кода с помощью throw  new Exception();. 

Расскажи про информацию, которая находится внутри исключения? Как с ней работать?

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

В Java каждый класс исключения имеет ряд свойств (fields) и методов (methods), которые позволяют получить доступ к информации, содержащейся в исключении. Некоторые из наиболее распространенных свойств и методов:

getMessage() - возвращает строку, которая описывает причину исключения;

getCause() - возвращает объект Throwable, который был причиной этого исключения;

getStackTrace() - возвращает массив объектов StackTraceElement, который представляет стек вызовов методов, когда исключение было брошено;

toString() - возвращает строковое представление исключения, которое обычно включает имя класса исключения и его сообщение.

Для получения доступа к этой информации, можно использовать ключевое слово "catch", чтобы перехватить исключение, и вызвать один из методов класса исключения. Например, в следующем коде сообщение об ошибке будет выведено на консоль:

try {

// код, который может бросить исключение

} catch (Exception e) {

System.out.println("Ошибка: " + e.getMessage());

}

Можно получить более подробную информацию, например, стек вызовов методов, который привел к исключению, вы можете вызвать метод getStackTrace() объекта исключения. Например:

try {

// код, который может бросить исключение

} catch (Exception e) {

System.out.println("Ошибка: " + e.getMessage());

e.printStackTrace();

}

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


Что такое подавленные исключения? Как достать подавленное исключение?

Подавленное исключение (suppressed exception) - это исключение, которое было брошено в блоке "finally" после того, как уже было брошено первоначальное исключение.

В Java 7 была добавлена новая функциональность, позволяющая сохранять подавленные исключения. Если в блоке "finally" возникает исключение, и в блоке try-catch также возникает исключение, то второе исключение становится подавленным. Это значит, что оно не будет брошено и будет добавлено к первоначальному исключению в качестве подавленного исключения.

Чтобы достать подавленное исключение, можно использовать метод getSuppressed(), который возвращает массив всех подавленных исключений для данного объекта исключения. Например, в следующем коде мы создаем два исключения, одно из которых подавляется, а затем выводим на экран все подавленные исключения:

public class SuppressedExceptionsExample {

public static void main(String[] args) {

try {

throwException();

} catch (Exception e) {

System.out.println("Первоначальное исключение: " + e.getMessage());

for (Throwable suppressed : e.getSuppressed()) {

System.out.println("Подавленное исключение: " + suppressed.getMessage());

}

}

}

public static void throwException() throws Exception {

try {

throw new Exception("Первое исключение");

} finally {

throw new Exception("Второе исключение");

}

Результат работы программы:

Первоначальное исключение: Второе исключение

Подавленное исключение: Первое исключение

В данном примере первое исключение было брошено в блоке try, а второе исключение было брошено в блоке finally. Второе исключение подавлено и добавлено к первому исключению в качестве подавленного исключения. Метод getSuppressed() позволяет получить доступ к подавленному исключению и вывести его сообщение на экран.

Какую информацию можно получить из StackTraceElement?

Класс StackTraceElement представляет один элемент из трассировки стека вызовов (stack trace), который позволяет узнать информацию о месте, где было вызвано исключение.

Каждый объект StackTraceElement содержит следующую информацию:

имя класса, в котором произошло исключение (getClassName());

имя метода, в котором произошло исключение (getMethodName());

имя файла исходного кода, в котором произошло исключение (getFileName());

номер строки исходного кода, на которой произошло исключение (getLineNumber()).

Кроме того, класс StackTraceElement имеет несколько методов, которые могут быть полезны при работе с трассировкой стека вызовов, например: