Исключения Java - это механизм последовательности, предоставляемый Java для выявления и реагирования на ошибки.
Механизм исключений Java может отделить код обработки исключений в программе от обычного бизнес -кода, гарантировать, что программный код является более элегантным и улучшит надежность программы. При эффективном использовании исключений исключение может четко ответить на эти три вопроса: тип исключения отвечает «Что» и трассировку стека исключений «где» и информация о исключении «почему» брошен.
Несколько ключевых слов, используемых в механизме исключений Java: попробуйте, поймайте, наконец, бросает, бросает.
| Ключевые слова | иллюстрировать |
|---|---|
| пытаться | Используется для прослушивания. Поместите код, который будет слушать (код, который может бросить исключение) в блоке операторов try. Когда в блоке операторов TRY происходит исключение, исключение брошено. |
| ловить | Используется, чтобы поймать исключения. Улов используется для улавливания исключений, которые происходят в блоках операторов TRY. |
| Окончательно | Наконец, блоки операторов всегда будут выполнены. В основном он используется для переработки ресурсов материала (таких как подключения к базе данных, сетевые подключения и файлы дисков), открытые в блоках TRY. Только после выполнения окончательного блока будет возвращать или бросить операторы в блоке Try или Catch. Если используются последние операторы, такие как возврат или бросок, они не будут возвращаться к исполнению и останутся напрямую. |
| бросать | Используется для бросания исключений. |
| броски | Используется в подписях метода для объявления исключений, которые могут быть брошены методом. |
открытый класс demo1 {public static void main (string [] args) {try {int i = 10/0; System.out.println ("i ="+i); } catch (arithmeticexception e) {System.out.println ("пойман исключение"); System.out.println ("e.getMessage ():" + e.getMessage ()); System.out.println ("e.toString ():" + e.toString ()); System.out.println ("e.printstacktrace ():"); e.printstacktrace (); }}} Результаты работы:
Занят excecute.getMessage (): / by zeroe.tostring (): java.lang.arithmeticexception: / by zeroe.printstacktrace (): java.lang.arithmeticexception: / by Zero at demo1.main (demo1.java:6)
Описание результата: в блоке оператора TRY есть операция с делителем 0, и операция бросит исключение java.lang.arithmeticexception. По ловли, исключение поймано.
Наблюдая за результатами, которые мы обнаружили, что System.out.println ("i ="+i) не была выполнена. Это означает, что после исключения в блоке операторов TRY оставшийся контент в блоке оператора TRY больше не будет выполняться.
Пример 2: Поймите основное использование наконец
На основе «Пример один» мы добавляем окончательно утверждения.
открытый класс demo2 {public static void main (string [] args) {try {int i = 10/0; System.out.println ("i ="+i); } catch (arithmeticexception e) {System.out.println ("пойман исключение"); System.out.println ("e.getMessage ():" + e.getMessage ()); System.out.println ("e.toString ():" + e.toString ()); System.out.println ("e.printstacktrace ():"); e.printstacktrace (); } наконец {system.out.println ("run inlocal"); }}} Результаты работы:
Занят exceptione.getmessage (): / by zeroe.tostring (): java.lang.arithmeticexception: / by zeroe.printstacktrace (): java.lang.arithmeticexception: / by Zero at demo2.
Результаты: наконец -то был выполнен блок оператора.
Пример 3: Понять основное использование бросков и бросков
Выбросы используются для объявления брошенных исключений, в то время как бросок используется для бросания исключений.
класс myexception расширяет Exception {public myException () {} public myexception (String msg) {super (msg); }} открытый класс demo3 {public static void main (string [] args) {try {test (); } catch (myException e) {System.out.println ("поймать мое исключение"); e.printstacktrace (); }} public static void test () Throws MyException {try {int i = 10/0; System.out.println ("i ="+i); } catch (arithmeticexception e) {бросить новое myexception («Это myexception»); }}} Результаты работы:
Поймайте мое исключение.
Результаты: MyException - это подкласс, унаследованный от исключения. Исключение arithmeticexception (разделитель равен 0) генерируется в блоке оператора try of test (), и исключение попадает в улов; Тогда исключение Myexception брошен. Метод Main () захватывает микспенцию, брошенную в тест ().
Java Exception Framework
Архитектурная схема исключений Java:
1
Throwable - это суперкласс всех ошибок или исключений на языке Java.
Throwable содержит два подкласса: ошибка и исключение. Они обычно используются для указания аномалии.
Throwable содержит снимки потока, выполняющего стек при создании его потока. Он предоставляет интерфейсы, такие как printStackTrace (), чтобы получить информацию, такую как данные трассировки стека.
2. Исключение
Исключение и его подклассы являются формой броска, которая указывает на условия, которые разумное приложение хочет захватить.
3. runtimeexception
Runtimeexception - это суперкласс, который может бросить исключения во время обычной работы виртуальной машины Java.
Компилятор не проверяет исключения Runtimeexception. Например, когда делитель равен нулю, исключение арифметикексии. Runtimeexception - это суперкласс Arithmeticexception. Когда код имеет делитель нуля, его также можно скомпилировать, если он «не будет проведен через объявление бросков» или «не обрабатывается через попытку ... поймать ...». Это то, что мы говорим: «Компилятор не проверяет исключения Runtimeexception»!
Если код генерирует исключение Runtimeexception, его необходимо избежать путем изменения кода. Например, если делитель равен нулю, вам необходимо избежать этой ситуации через код!
4. Ошибка
Как и исключение, ошибка также является подклассом броски. Он используется для обозначения серьезных проблем, которые разумное приложение не должно пытаться поймать, и большинство таких ошибок являются исключительными условиями.
Как и Runtimeexception, компилятор не будет проверять ошибку.
Java делит бросаемую структуру на три типа: проверенное исключение (проверено исключение), исключение времени выполнения (Runtimeexception) и ошибка (ошибка).
(1) Исключение времени выполнения
Определение: Runtimeexception и его подклассы называются исключениями во время выполнения.
Особенности: Компилятор Java не будет проверять его. То есть, когда такое исключение может произойти в программе, если оно «не выдвинуто через объявление бросков» или «не поймано с помощью заявления о попытках», оно все равно будет составлено и передано. Например, исключение Arithmeticexception, генерируемое, когда делитель равен нулю, исключение IndexoutOfBoundSexception, генерируемое, когда массив выходит за пределы, исключение CORRURentModificationException, генерируемое механизмом Fail Fail и т. Д., Это все исключения времени выполнения.
Хотя компилятор Java не проверяет исключения во время выполнения, мы также можем объявить и бросить его через броски или запечатлеть его через Try-Catch.
Если генерируется исключение времени выполнения, его необходимо избежать путем изменения кода. Например, если делитель равен нулю, вам необходимо избежать этой ситуации через код!
(2) Проверено исключение
Определение: сам класс исключений и другие подклассы в подклассах исключения, за исключением «Исключения времени выполнения», все считаются проверенными исключениями.
Особенности: Компилятор Java проверит это. Такие исключения либо объявляются, и бросаются через броски, либо захватываются через Try-Catch, в противном случае они не могут быть составлены. Например, ClonenotSupportedException является проверенным исключением. Когда объект клонируется через интерфейс Clone (), а соответствующий класс объекта не реализует клонируемый интерфейс, будет брошено клоненотсупорноэкспений.
Исключения, которые проверяются, обычно могут быть восстановлены.
(3) Ошибка
Определение: класс ошибок и его подклассы.
Особенности: Как и исключения во время выполнения, компилятор не будет проверять ошибки.
Ошибка возникает, когда существует недостаточное количество ресурсов, сбоя ограничений или других условий, которые не могут продолжать выполнять другие программы. Сама программа не может исправить эти ошибки. Например, VirtualMachineError - ошибка.
Согласно Java Convention, мы не должны реализовать какие -либо новые подклассы ошибок!
Для приведенных выше трех структур, какую из них мы должны бросить исключение или ошибку? Рекомендация, приведенная в «Эффективной Java»: Используйте проверенные исключения для условий, которые можно восстановить, и используйте исключения времени выполнения для ошибок программы.
Несколько предложений по обработке исключений
Статья 1: Используйте исключения только для ненормальных ситуаций
Рекомендация: исключения должны использоваться только для аномальных условий, и их никогда не следует использовать для нормальных контрольных потоков.
Объяснение сделано путем сравнения двух кодов ниже.
Код 1
попробуйте {int i = 0; while (true) {arr [i] = 0; i ++; }} catch (indexoutOfBoundSexception e) {} code 2For (int i = 0; i <arr.length; i ++) {arr [i] = 0;} Цель обоих кодов состоит в том, чтобы итерация над массивом ARR и установить значение каждого элемента в массиве на 0. Код 1 заканчивается исключением, что, кажется, очень трудно понять, код 2 завершается границами массива. Мы должны избегать использования кода 1 по трем основным причинам:
Первоначальный дизайн механизмов исключений предназначен для ненормальных ситуаций, поэтому лишь немногие реализации JVM пытаются оптимизировать их производительность. Следовательно, накладные расходы создания, броска и улавливания исключений стоят дорого.
Помещение кода в Try-Catch возврат предотвращает реализацию определенных конкретных оптимизаций, которые могли бы быть выполнены.
Стандартная схема пересечения массивов не приводит к избыточным чекам, и некоторые современные реализации JVM будут оптимизировать их.
На самом деле, режимы на основе исключений намного медленнее, чем стандартные режимы. Тестовый код заключается в следующем:
Общедоступный класс. Частный статический размер int = 10000; public static void main (string [] args) {long s1 = System.currentTimeMillis (); для (int i = 0; i <size; i ++) endbyrange (arr); long e1 = system.currenttimemillis (); System.out.println ("EndbyRange Time:"+(E1-S1)+"MS"); long s2 = System.currentTimeMillis (); для (int i = 0; i <size; i ++) endbyexception (arr); long e2 = system.currenttimemillis (); System.out.println ("EndbyException Time:"+(E2-S2)+"MS"); } // пройти массив ARR: Private Static void EndByException (int [] arr) {try {int i = 0; while (true) {arr [i] = 0; i ++; //System.out.println("endbyrange: arr ["+i+"] = "+arr [i]); }} catch (indexoutofboundsexception e) {}} // Передача массива ARR: Private Static void EndByRange (int [] arr) {for (int i = 0; i <arr.length; i ++) {arr [i] = 0; //System.out.println("endbyexception: arr ["+i+"] = "+arr [i]); }}} Результаты работы:
EndbyRange Время: 8msendbyException Время: 16 мс
Результат показывает, что скорость пересечения исключения намного медленнее, чем обычное обход массива!
Статья 2: Используйте проверенные исключения для восстановления условий и используйте исключения времени выполнения для ошибок программы.
| аномальный | иллюстрировать |
|---|---|
| Исключение времени выполнения | Класс Runtimeexception и его подклассы называются исключениями во время выполнения. |
| Проверенное исключение | Сам класс исключений, а также другие подклассы в исключении, за исключением «Исключения времени выполнения» - все это проверенные исключения. |
Разница в том, что компилятор Java проверяет «проверенные исключения» и не проверяет «исключения во время выполнения».
То есть, для проверенного исключения, оно либо объявляется и бросается через броски, либо захватывается через Try-Catch, в противном случае его нельзя составить. Что касается исключений во время выполнения, если они «не будут выдвинуты через объявление бросков» или «не пойманы с заявлением о попытке», они все равно будут составлены и переданы. Конечно, хотя компилятор Java не проверяет исключения во время выполнения, мы также можем объяснить исключение с помощью бросков или поймать его через Try-Catch.
Rithmeticexception (например, Divisor - 0), IndexoutofBoundSexception (например, массив из границ) и т. Д. - все это исключения во время выполнения. Для этого исключения мы должны избежать его, изменяя код. Для зарегистрированного исключения программа может быть восстановлена, чтобы запустить обработку. Например, предположим, что, поскольку пользователь не хранит достаточное количество вызовов, он потерпит неудачу при попытке позвонить на вызов за оплату труда; Таким образом, бросая проверенное исключение.
Статья 3: Избегайте ненужного использования проверенных исключений
«Исключение по цензуре» - хорошая особенность Java. В отличие от кода возврата, «проверенные исключения» заставляют программиста справиться с условиями исключения, значительно повышая надежность программы.
Тем не менее, чрезмерное использование проверенных исключений может сделать API очень неудобным. Если метод бросает одно или несколько проверяемых исключений, код, который вызывает метод, должен обрабатывать эти исключения в одном или нескольких блоках операторов Catch, или они должны быть выброшены через объявление бросков. Независимо от того, обрабатывается ли он с помощью вылова или бросается через объявления бросков, он добавляет невыплачиваемое бремя для программистов.
Два условия должны быть выполнены для «проверенных исключений»: во -первых, даже если API используется правильно, он не может предотвратить возникновение условий исключения. Во -вторых, как только генерируется исключение, программисты, использующие API, могут предпринять полезные действия для обработки программы.
Статья 4: Попробуйте использовать стандартные исключения
Повторное использование кода заслуживает адвокации, это общее правило, и исключения не являются исключением. Есть несколько преимуществ для повторного использования существующих исключений:
Во -первых, это облегчает ваш API для изучения и использования, потому что он согласуется с идиомами, с которыми программисты ознакомились.
Во -вторых, для программ, которые используют эти API, они лучше читаемые, потому что они не заполнены исключениями, которые не знакомы программистам.
В -третьих, тем меньше классов исключений, тем меньше использование памяти и меньшее время, потраченное на перепечатку этих классов.
Некоторые из стандартных исключений Java часто используются исключениями. Следующая таблица:
| аномальный | Используйте случаи |
|---|---|
| Нелегаларгументация | Значение параметра не подходит |
| AllodalStateException | Параметры не являются неуместными |
| NullPointerException | Когда NULL отключено, значение параметра равна нулю |
| Indexoutofboundsexception | Подписк пересекает границу |
| ConcurrentModificationException | Когда одновременная модификация запрещена, объект обнаруживает одновременную модификацию |
| UnsupportedOperationException | Методы, которые объект не поддерживает запросы клиентов |
Несмотря на то, что они являются наиболее часто используемыми исключениями библиотек платформ Java на сегодняшний день, другие исключения также могут быть использованы в условиях лицензии. Например, если вы хотите реализовать арифметические объекты, такие как комплексные числа или матрицы, было бы очень уместно повторно использовать Arithmeticexception и NumberFormateXception. Если исключение удовлетворяет ваши потребности, не стесняйтесь использовать его, но вы должны убедиться, что условие выброса исключения согласуется с условиями, описанными в документации для исключения. Это повторное использование должно основываться на семантике, а не на имени!
Наконец, обязательно поясните, что при выборе того, какое исключение для повторного использования не должно соблюдать правила. Например, с учетом случая карты объекта, предположим, что существует метод для операций по решению, а его параметр (Persistize) - это количество карт, которые должны быть даны в руке. Предположим, что вызывающий абонент передает значение в этом параметре, превышающем оставшееся количество карт для всей колоды. Затем эту ситуацию можно интерпретировать как нелегаларггментация (ценность Persionize слишком велика) или незаконное статей (у объекта карты слишком мало карт по сравнению с запросом клиента).
Статья 5: Исключение, которое должно быть подходящим для соответствующей абстракции
Эта ситуация может быть ошеломляющей, если исключение, сброшенное методом, не имеет очевидной корреляции с задачей, которую она выполняет. Это часто случается, когда метод проходит исключение, брошенное низкоуровневым абстракцией. Когда это происходит, это не только сбивает с толку, но и «загрязняет» API высокого уровня.
Чтобы избежать этой проблемы, реализация высокого уровня должна улавливать исключение низкого уровня и бросить исключение, которое может быть введено в соответствии с абстракцией высокого уровня. Эта практика называется «перевод исключений».
Например, метод сбора Java Collection Abstract Sectrediantlist get () выглядит следующим образом (на основе JDK1.7.0_40):
public e get (int index) {try {return listeriterator (index) .next (); } catch (noschelementException exc) {бросить новый indexoutofboundsexception ("index:"+index); }}ListIterator (Index) вернет объект ListIterator. Вызов следующий () метод объекта может бросить исключение Noshelementexception. В методе get () выброс исключения noshelementexception будет сбивает с толку. Таким образом, get () захватывает nochelementexception и бросает исключение IndexoutofBoundSexception. То есть он эквивалентен преобразованию noshelementexception в исключение Indexoutofboundsexception.
Статья 6: Исключение, которое должно быть задокументировано каждым методом
Чтобы объявить проверенное исключение отдельно, и используйте метку @Throws of Javadoc, чтобы точно записать условия для каждого исключения, которое можно было бросить.
Если многие методы в классе бросают одно и то же исключение по одной и той же причине, приемлемо выполнять документацию для этого исключения в комментариях к документу этого класса, а не документировать индивидуально для каждого метода.
Статья 7: Включите в подробную информацию о сбое
Короче говоря, когда мы настраиваем или бросаем исключение, мы должны включить информацию, связанную с отказом.
Когда программа не удается из -за исключения, система автоматически распечатает трассировку стека исключения. Содержит строковое представление исключения в дорожке стека. Обычно он содержит имя класса класса исключений, а также подробное сообщение, которое следует.
Статья 8: Стремясь поддерживать атомность в сбое
Когда объект бросает исключение, мы всегда ожидаем, что объект остается в четко определенном доступном состоянии. Это особенно важно для проверенного исключения, потому что вызывающий абонент обычно ожидает восстановления после проверенного исключения.
Вообще говоря, неудачный вызов метода должен держать объект в «его состоянии до его названия». Методы с такими атрибутами называются «сбой атомной». Можно понять, что неудача все еще поддерживает атомичность. Есть несколько способов поддержания «неудачной атомности»:
(1) Разработка не обдуманного объекта.
(2) Для методов, которые выполняют операции на изменяемых объектах, наиболее распространенным способом получения «неудачной атомичности» является проверка достоверности параметров перед выполнением операции. Следующим образом (метод POP в Stack.java):
public Object pop () {if (size == 0) бросить новый emptystackexception (); Object result = elements [-size]; Элементы [размер] = null; вернуть результат;} (3) Аналогично предыдущему методу, обработка расчетов может быть скорректирована, так что любая возможная сбой детали расчета произошла до изменения состояния объекта.
(4) Напишите код восстановления, чтобы объяснить сбои во время операции и чтобы объект перевернулся в состояние до начала операции.
(5) Выполните операцию во временной копии объекта, и после завершения операции скопируйте результат во временной копии на исходный объект.
В то время как «поддержание неудачной атомичности объекта» является желаемой целью, это не всегда возможно. Например, если несколько потоков пытаются одновременно получить доступ к объекту без надлежащих механизмов синхронизации, объект может оставаться в непоследовательном состоянии.
Даже в ситуациях, когда может быть достигнута «неудачная атомичность», это не всегда ожидается. Для некоторых операций это может значительно увеличить накладные расходы или сложность.
Общее правило: как часть спецификации метода, никакое исключение не должно изменить состояние объекта, прежде чем вызовать метод. Если это правило нарушено, документация API должна четко указать, в каком состоянии будет объект.
Статья 9: Не игнорируйте исключения
Когда дизайнер API заявляет, что метод вызовет исключение, они пытаются что -то проиллюстрировать. Так что, пожалуйста, не игнорируйте это! Код, чтобы игнорировать исключения, заключается в следующем:
try {...} catch (someexception e) {} Пустой блок улова заставит исключение не в достижении своей должной цели. Цель исключения - заставить вас справиться с ненормальными условиями. Игнорирование исключения - это все равно, что игнорировать сигнал пожарной сигнализации - если сигнал пожарной сигнализации выключен, то никто не увидит сигнал пожарной сигнализации, когда возникает настоящий огонь. Таким образом, по крайней мере блок улова должен содержать описание, которое объясняет, почему уместно игнорировать это исключение.