Что такое подавленные исключения java
Что такое подавленное исключение?
Комментарий (пользователь soc) в ответ на вопрос об оптимизации хвостовых опций упоминал, что Java 7 имеет новую функцию, называемую «подавленные исключения», из-за «добавления ARM» (поддержка процессоров ARM?).
Что такое «исключенное исключение» в этом контексте? В других контекстах «исключенное исключение» было бы исключением, которое было поймано, а затем проигнорировано (редко хорошая идея); это явно что-то другое.
ОТВЕТЫ
Ответ 1
Я полагаю, что комментатор ссылается на это исключение, которое игнорируется, когда оно выбрано внутри неявного блока finally try-with-resources, в контексте того, что существующее исключение выбрано из блока try :
Исключение может быть выбрано из блока кода, связанного с оператором try-with-resources. В примере writeToFileZipFileContents исключение может быть выбрано из блока try, и до двух исключений может быть выбрано из инструкции try-with-resources при попытке закрыть объекты ZipFile и BufferedWriter. Если исключение выбрано из блока try, и одно или несколько исключений выбрасываются из оператора try-with-resources, то те исключения, которые выбраны из инструкции try-with-resources, подавляются, а исключение, созданное блоком, является тем, который вызывается методом writeToFileZipFileContents. Вы можете получить эти подавленные исключения, вызвав метод Throwable.getSuppressed из исключения, созданного блоком try.
(Это цитирует раздел «Подавленные исключения» на связанной странице.)
Ответ 2
Компилятор должен определить, какой из них «действительно» бросить. Он выбирает исключение, выраженное в явном коде (код в блоке try ), а не в том, что выбрано неявным кодом (блок finally ). Поэтому исключение (исключения), которое бросается в неявный блок, подавляется (игнорируется). Это происходит только в случае нескольких исключений.
Ответ 3
До Java7; В коде есть исключения, которые были проигнорированы.
В класс Throwable в JDK 7 был добавлен новый конструктор и два новых метода. Они приведены ниже:
с помощью этого нового подхода мы также справимся с этим исключенным исключением.
В Java7 try-with-resources; исключение в AutoCloseable:: close() добавляется как исключенное исключение по умолчанию вместе с исключением try.
Также известно, что это отличается от цепочки исключений (были введены с JDK 1.4 и были предназначены для того, чтобы можно было легко отслеживать причинно-следственные связи между исключениями.)
Ответ 4
Подавленные исключения являются дополнительными исключениями, которые происходят в инструкции try-with-resources (представленный в Java 7), когда AutoCloseable ресурсы закрыты. Поскольку при закрытии ресурсов AutoCloseable могут возникать множественные исключения, дополнительные исключения исключаются из в качестве исключенных исключений.
Ответ 5
Выполнение кода ниже:
Со всеми строками вы получите: java.lang.RuntimeException: from finally!
Удаление блока finally вы получите: java.lang.RuntimeException: from catch!
Удаление блока catch вы получите:
Ответ 6
Я думаю, что это связано с «цепным средством исключения». Это повлияет на то, каким образом исключение обрабатывается этим средством по мере развития трассировки стека. Со временем исключения, которые являются частью группы связанных исключений, могут быть подавлены. Подробнее см. Throwable documentation.
Ответ 7
Возьмем очень простой пример
Я собрал большинство возможных сценариев с фрагментами кода и выводами в следующем сообщении.
Надеюсь, что это поможет.
Ответ 8
Вы также можете подавлять исключения на Java 6 (вовлеченный небольшой обман),
Я создал утилиту, которая прозрачно обрабатывает исключение исключения в Java 1.6 и Java 1.7. Вы можете найти реализацию здесь
Все, что вам нужно, это позвонить:
чтобы исключить исключение, и
чтобы получить исключенные исключения из Exception, если кто-либо еще использует Java 1.6
Что такое подавленное исключение?
комментарий (пользователем soc) на ответ to вопрос об оптимизации хвостового вызова упомянуто, что Java 7 имеет новую функцию, называемую «подавленными исключениями», из-за» добавления ARM » (поддержка процессоров ARM?).
Что такое «подавленное исключение» в этом контексте? В других контекстах «подавленное исключение» было бы исключением, которое было поймано, а затем проигнорировано (редко хорошая идея); это явно что-то отличающийся.
8 ответов
Я считаю, что комментатор ссылается на исключение, которое наполовину игнорируется, когда оно бросается в неявном finally блок try-with-resources блок, в контексте существующего исключения из try блок:
исключение может быть вызвано из блока кода, связанного с инструкцией try-with-resources. В Примере writeToFileZipFileContents из блока try может быть создано исключение и до двух исключения могут быть вызваны из инструкции try-with-resources при попытке закрыть объекты ZipFile и BufferedWriter. Если исключение из try блока и одного или нескольких исключений из try-оператор с ресурсами, то эти исключения из try-оператор с ресурсами подавляются, и исключение в блоке-это одно, что бросается writeToFileZipFileContents способ. Эти подавленные исключения можно получить, вызвав Перекидным.метод getSuppressed из исключения, создаваемого блоком try.
(это цитирование раздела под названием «подавленные исключения» со связанной страницы.)
компилятор должен определить, какой из них» действительно » бросить. Он решает выбросить исключение, вызванное в явном коде (код в try заблокировать) вместо того, чтобы бросать неявный код ( finally блок). Поэтому исключения, создаваемые в неявном блоке, подавляются (игнорируются). Это происходит только в случае нескольких исключений.
перед Java7; в коде есть исключения, но они были проигнорированы каким-то образом.
новый конструктор и два новых метода были добавлены в класс Throwable в JDK 7. Это, как показано ниже:
С этим новым подходом мы также можем справиться с этими подавленными исключениями.
В Java7 try-with-resources; исключение в AutoCloseable:: закрыть() по умолчанию добавляется как подавленное исключение вместе с исключением try.
также известно, что это отличается от цепи исключений (были введены с JDK 1.4 и были предназначены, чтобы сделать возможным легко отслеживать причинно-следственные связи между исключениями.)
подавленных исключений являются дополнительными исключениями, которые происходят в инструкции try-with-resources (введено в Java 7) при AutoCloseable ресурсы закрыты. Потому что при закрытии может произойти несколько исключений AutoCloseable ресурсы, дополнительные исключения прилагаются к первичное исключение как подавленные исключения.
глядя на байт-код фрагмента образца кода try-with-resources, standard в JVM обработчики исключений используются для размещения семантики try-with-resources.
Concedering код ниже:
со всеми линиями, вы получите: java.lang.RuntimeException: from finally!
удаление finally блок вы получите: java.lang.RuntimeException: from catch!
удаление catch блок вы получите:
Я думаю, что это связано с «прикованным средством исключения». Это повлияет на то, как исключение обрабатывается этим средством по мере развития трассировки стека. Со временем исключения, входящие в группу связанных исключений, могут быть подавлены. Посмотреть Throwable documentation для более подробной информации.
вы также можете подавлять исключения в Java 6 (немного обмана),
Я создал утилиту, которая прозрачно обрабатывает подавление исключений в Java 1.6 и Java 1.7. Вы можете найти реализацию здесь
все, что вам нужно, это позвонить:
чтобы подавить исключение, и
чтобы получить подавленные исключения исключения, в случае, если кто-то все еще использует Java 1.6
ARM-автоматическое управление ресурсами (введено с Java 7)
Обработка исключений в Java: Полное руководство с лучшими и наихудшими практиками
Обзор
Обработка исключений в Java-одна из самых основных и фундаментальных вещей, которые разработчик должен знать наизусть. К сожалению, это часто упускается из виду, а важность обработки исключений недооценивается – это так же важно, как и остальная часть кода.
В этой статье давайте рассмотрим все, что вам нужно знать об обработке исключений в Java, а также о хороших и плохих методах.
Что такое Обработка исключений?
Мы ежедневно сталкиваемся с обработкой исключений в реальной жизни.
При заказе товара в интернет – магазине-товара может не быть в наличии на складе или может произойти сбой в доставке. Таким исключительным условиям можно противостоять, изготовив другой продукт или отправив новый после сбоя в доставке.
При создании приложений – они могут столкнуться со всевозможными исключительными условиями. К счастью, будучи опытным в обработке исключений, таким условиям можно противостоять, изменив поток кода.
Зачем использовать обработку исключений?
При создании приложений мы обычно работаем в идеальной среде – файловая система может предоставить нам все файлы, которые мы запрашиваем, наше подключение к Интернету стабильно, а JVM всегда может предоставить достаточно памяти для наших нужд.
Если мы не справимся с такими условиями, все приложение окажется в руинах, а весь остальной код устареет. Поэтому мы должны уметь писать код, который может адаптироваться к таким ситуациям.
Представьте, что компания не может решить простую проблему, возникшую после заказа продукта, – вы не хотите, чтобы ваше приложение работало таким образом.
Иерархия исключений
Все это просто напрашивается вопрос – каковы эти исключения в глазах Java и JVM?
В конце концов, исключения-это просто объекты Java, которые расширяют интерфейс Throwable :
Когда мы говорим об исключительных условиях, мы обычно имеем в виду одно из трех:
Примечание : Термины “Время выполнения” и “Непроверенный” часто используются взаимозаменяемо и относятся к одному и тому же типу исключений.
Проверенные Исключения
Проверенные исключения-это исключения, которые мы обычно можем предвидеть и планировать заранее в нашем приложении. Это также исключения, которые компилятор Java требует, чтобы мы либо обрабатывали, либо объявляли при написании кода.
Правило обработки или объявления относится к нашей ответственности за то, чтобы либо объявить, что метод создает исключение в стеке вызовов, не предпринимая особых усилий для его предотвращения, либо обработать исключение с помощью нашего собственного кода, что обычно приводит к восстановлению программы из исключительного состояния.
Непроверенные Исключения
Им часто можно противостоять, реализуя простые проверки перед сегментом кода, который потенциально может быть использован таким образом, чтобы сформировать исключение во время выполнения, но об этом позже.
Ошибки
Ошибки-это самые серьезные исключительные условия, с которыми вы можете столкнуться. От них часто невозможно избавиться, и нет реального способа справиться с ними. Единственное, что мы, как разработчики, можем сделать, – это оптимизировать код в надежде, что ошибки никогда не возникнут.
Как обрабатывать исключения
бросок и броски
Самый простой способ устранить ошибку компилятора при работе с проверенным исключением – просто выбросить ее.
Имейте в виду, что любой, кто вызывает этот метод, также должен следовать правилу обработки или объявления.
При создании исключения мы можем либо создать новое исключение, как в предыдущем примере, либо пойманное исключение.
попробуйте-поймайте блоки
Более распространенным подходом было бы использовать try – catch блок для перехвата и обработки возникающего исключения:
Этот код пытается прочитать содержимое файла, и если файл не найден, исключение FileNotFoundException | поймано и повторно обработано . Подробнее на эту тему позже.
Запуск этого фрагмента кода без допустимого URL-адреса приведет к появлению исключения:
В качестве альтернативы, мы можем попытаться оправиться от этого состояния вместо того, чтобы бросать:
Запуск этого фрагмента кода без действительного URL-адреса приведет к:
наконец, Блоки
Вводя новый тип блока, блок наконец выполняется независимо от того, что происходит в блоке try. Даже если он внезапно завершится созданием исключения, блок finally будет выполнен.
Однако этот подход был осужден после выпуска Java 7, которая представила лучший и более чистый способ закрытия ресурсов, и в настоящее время рассматривается как плохая практика.
заявление о попытке использования ресурсов
Ранее сложный и подробный блок может быть заменен:
Кроме того, вы можете включить в этот блок несколько ресурсов, один за другим:
Таким образом, вам не нужно беспокоиться о закрытии ресурсов самостоятельно, так как блок try-with-resources гарантирует, что ресурсы будут закрыты в конце инструкции.
Несколько блоков захвата
Когда код, который мы пишем, может выдавать более одного исключения, мы можем использовать несколько блоков catch для обработки их по отдельности:
Когда блок try вызывает исключение, JVM проверяет, является ли первое пойманное исключение подходящим, и если нет, продолжает, пока не найдет его.
Примечание : При перехвате общего исключения будут перехвачены все его подклассы, поэтому не требуется перехват их отдельно.
Таким образом, мы можем обрабатывать более конкретное исключение иным способом, чем более общее.
Примечание : При перехвате нескольких исключений компилятор Java требует, чтобы мы помещали более конкретные исключения перед более общими, иначе они были бы недоступны и привели бы к ошибке компилятора.
Блоки захвата соединения
Чтобы уменьшить шаблонный код, в Java 7 также были введены блоки union catch/|. Они позволяют нам одинаково обрабатывать несколько исключений и обрабатывать их исключения в одном блоке:
Как создавать исключения
Иногда мы не хотим обрабатывать исключения. В таких случаях мы должны заботиться только о том, чтобы генерировать их, когда это необходимо, и позволять кому-то другому, вызывающему наш метод, обрабатывать их соответствующим образом.
Создание проверенного исключения
Когда что-то идет не так, например, количество пользователей, подключающихся в настоящее время к нашему сервису, превышает максимальную сумму, которую сервер может легко обработать, мы хотим создать исключение, чтобы указать на исключительную ситуацию:
Git Essentials
Ознакомьтесь с этим практическим руководством по изучению Git, содержащим лучшие практики и принятые в отрасли стандарты. Прекратите гуглить команды Git и на самом деле изучите это!
Этот код будет увеличивать количество Пользователей до тех пор, пока не превысит максимально рекомендуемую сумму, после чего он выдаст исключение. Поскольку это проверяемое исключение, мы должны добавить предложение throws в подпись метода.
Определить подобное исключение так же просто, как написать следующее:
Создание непроверенного исключения
Поскольку мы создаем исключение runtimeexception, нет необходимости включать его в подпись метода, как в приведенном выше примере, но это часто считается хорошей практикой, по крайней мере, для документации.
Опять же, определить пользовательское исключение во время выполнения, подобное этому, так же просто, как:
Бросание
Создание исключения упоминалось ранее, поэтому вот краткий раздел для уточнения:
Повторное выбрасывание относится к процессу выбрасывания уже пойманного исключения, а не к выбрасыванию нового.
Обертывание
Обертывание, с другой стороны, относится к процессу обертывания уже пойманного исключения в другое исключение:
Бросание бросаемого или _Exception*?
Эти классы верхнего уровня могут быть пойманы и переосмыслены, но как это сделать, может варьироваться:
Однако, если мы создадим проверенное исключение в методе:
Наследование исключений
Подклассы, наследующие метод, могут создавать только меньшее количество проверенных исключений, чем их суперкласс:
При таком определении следующий метод вызовет ошибку компилятора:
Лучшие и худшие методы обработки исключений
Учитывая все это, вы должны быть хорошо знакомы с тем, как работают исключения и как их использовать. Теперь давайте рассмотрим лучшие и худшие методы, когда дело доходит до обработки исключений, которые, мы надеемся, теперь полностью понятны.
Лучшие Методы Обработки Исключений
Избегайте Исключительных Условий
Иногда, используя простые проверки, мы можем вообще избежать формирования исключений:
Вызов этого метода с допустимым индексом приведет к:
Но вызов этого метода с индексом, который выходит за рамки, приведет к:
В любом случае, даже если индекс слишком высок, нарушающая строка кода не будет выполнена, и никаких исключений не возникнет.
Используйте попытку с ресурсами
Как уже упоминалось выше, всегда лучше использовать более новый, более лаконичный и чистый подход при работе с ресурсами.
Закройте ресурсы в try-catch-наконец-то
Если вы по какой-либо причине не используете предыдущий совет, по крайней мере, не забудьте закрыть ресурсы вручную в блоке “Наконец”.
Я не буду включать пример кода для этого, так как оба они уже были предоставлены для краткости.
Наихудшие Методы Обработки Исключений
Глотание Исключений
Если вы намерены просто удовлетворить компилятор, вы можете легко сделать это, проглотив исключение :
Проглатывание исключения относится к акту перехвата исключения и не устранения проблемы.
Таким образом, компилятор удовлетворен, так как исключение поймано, но вся соответствующая полезная информация, которую мы могли извлечь из исключения для отладки, потеряна, и мы ничего не сделали для восстановления после этого исключительного условия.
Еще одна очень распространенная практика-просто распечатать трассировку стека исключения:
Такой подход создает иллюзию управляемости. Да, хотя это лучше, чем просто игнорировать исключение, распечатав соответствующую информацию, это не справляется с исключительным условием больше, чем игнорирование.
Вернитесь в последний блок
Если выполнение блока try завершается внезапно по какой-либо другой причине R, то наконец блок выполняется, и тогда есть выбор.
Итак, в терминологии документации, если блок наконец завершается нормально, то оператор try завершается внезапно по причине R.
Если блок finally завершается внезапно по причинам, то оператор try завершается внезапно по причинам (и причина R отбрасывается).
Бросаю в последний блок
Очень похоже на предыдущий пример, использование throw в наконец блоке приведет к удалению исключения из try-catch блока:
Имитация оператора goto
Критическое мышление и творческие способы поиска решения проблемы-хорошая черта, но некоторые решения, какими бы творческими они ни были, неэффективны и избыточны.
И все же некоторые люди используют исключения для их имитации:
Использование исключений для этой цели неэффективно и медленно. Исключения предназначены для исключительного кода и должны использоваться для исключительного кода.
Лесозаготовки и метания
При попытке отладить фрагмент кода и выяснить, что происходит, не регистрируйте и не создавайте исключение:
Выполнение этого является избыточным и просто приведет к появлению множества сообщений журнала, которые на самом деле не нужны. Объем текста уменьшит видимость журналов.
Перехват исключения или Выбрасывание
Почему бы нам просто не перехватить исключение или Выбрасываемое, если оно улавливает все подклассы?
Если нет веской, конкретной причины поймать кого-либо из этих двоих, обычно не рекомендуется этого делать.
Перехват Исключения будет перехватывать как проверенные, так и исключения во время выполнения. Исключения во время выполнения представляют собой проблемы, которые являются прямым результатом проблемы программирования, и поэтому их не следует перехватывать, поскольку нельзя разумно ожидать, что они будут устранены или обработаны.
Вывод
В этой статье мы рассмотрели исключения и обработку исключений с нуля. После этого мы рассмотрели лучшие и худшие методы обработки исключений в Java.
Надеюсь, вы нашли этот блог информативным и образовательным, счастливого кодирования!
Одним из основных нововведений, которые были включены в Java 7, стало введение нового оператора «try c ресурсами». «try c ресурсами» это оператор try, в котором объявляются один или несколько ресурсов. Ресурс — это объект, который должен быть закрыт после того, как программа закончит с ним работу. «try c ресурсами» берет всю работу по закрытию ресурсов на себя. Прежде, чем подробно его рассмотреть давайте разберемся в причинах, которые вызвали его появление.
Закрытие ресурсов до Java 7.
Предположим нам нужно написать метод, который считывает первую строчку из одного файла и записывает ее в другой файл. Задача очень простая и ее реализация не должна вызвать каких-либо затруднений:
Слишком много кода для столь простой операции, не находите? Но и это еще не все, в коде выше есть существенный изъян, если при закрытии первого ресурса:
будет сгенерировано исключение, то второй ресурс закрыт не будет:
Самым очевидным выходом из данной ситуации – будет окружить закрытие ресурсов дополнительными блоками try:
Согласитесь, что выглядит ужасно, но до выхода Java 7 с этим приходилось мириться.
Использование try с ресурсами.
Появление оператора try с ресурсами значительно упростило жизнь программистам, больше не было необходимости громоздить конструкции try/catch в надежде, что ты закрыл все ресурсы и предусмотрел все возможные исключительные ситуации, большую часть этой работы try с ресурсами взял на себя. Рассмотрим его общий вид:
Главное отличие от привычного блока try в круглых скобках, в которых создаются ресурсы, которые впоследствии нужно закрыть, ресурсы будут закрываться снизу-вверх автоматически после завершения работы блока try, т.е. в примере, сначала закроется writer, а потом reader. Ресурсы созданные в блоке try(), в нашем случае reader и writer будут видны только в блоке try, в блоках catch и finally попытка их использования вызовет ошибку компиляции.
При использовании оператора try с ресурсами, совершенно не обязательно использовать блоки catch и finally, они являются опциональными, исходя из этого предыдущий пример можно переписать следующим образом:
Подобный код абсолютно легален и никаких ошибок компиляции не вызовет.
Настало время улучшить наш пример из начала статьи, который копирует первую строчку из одного файла в другой:
Получилось в два раза меньше кода, чем в первоначальном примере.
Интерфейс AutoCloseable.
Для того, чтобы класс можно было использовать в операторе try с ресурсами, он должен реализовывать интерфейс AutoCloseable. Хорошая новость, в том, что сделать это не так уж и сложно – необходимо реализовать всего лишь один метод – public void close() throws Exception.
Как и следовало ожидать сначала выполнился код из блока try, а потом произошло закрытие ресурса, с помощью переопределенного метода close(). Вы наверное заметили, что в примере, метод close() не генерирует и не объявляет никаких исключений, в отличии от метода объявленного в интерфейсе AutoCloseable – это вполне легально, переопределяемый метод может генерировать более конкретные исключения или не генерировать их вовсе. Еще на что хотелось бы обратить пристальное внимание, так это на саму реализацию метода close(). Метод close() не должен содержать никакой бизнес логики, только закрытие ресурсов:
Данный код конечно же скомпилируется, но закрытие ресурсов будет вызывать побочный эффект и изменять значение переменной, чего конечно же нужно избегать.
Подавленные исключения.
Подавленные исключения (suppressed exception) образуются, когда в блоке try генерируется исключение и в методе close() при закрытии ресурса генерируется исключение, в этом случае первое исключение считается главным остальные подавленные, чтобы было понятнее рассмотрим пример:
Вывод:
Main exception
Suppressed Exception
Suppressed Exception
В нашем случае получился следующий ход выполнения программы: сначала создаются два объекта Example ex1 и ex2, после чего происходит вход в блок try, где генерируется исключение, программа прекращает выполнения кода в блоке и приступает к закрытию ресурсов снизу-вверх. При закрытии каждого из ресурсов в методе close() генерируется еще по одному исключению, которые последовательно добавляются к главному исключению, сгенерированному в блоке try. После того, как ресурсы были закрыты, программа приступает к обработке исключения в блоке catch, где первой строчкой мы выводим информацию о главном исключении, а последующим циклом получаем подавленные исключения и выводим информацию о них.
Последнее на что стоит обратить внимание, так это, что подавленные исключения работают только в блоке try, в следующем примере будет сгенерировано два самостоятельных и независимых друг от друга исключения: