16 ответов:
вообще, никогда. Однако иногда вам нужно поймать определенные ошибки.
Если вы пишете код framework-ish (загрузка сторонних классов), было бы разумно поймать LinkageErrors (не найден класс def, неудовлетворенная ссылка, несовместимое изменение класса). Я также видел некоторые глупые сторонние коды, бросающие подкассы ошибок,поэтому вам придется справиться с ними.
кстати, я не уверен, что это не возможно, чтобы оправиться от OutOfMemory.
никогда. Вы никогда не можете быть уверены, что приложение способно выполнить следующую строку кода. Если вы получаете
OutOfMemoryError, вы нет гарантии, что вы сможете сделать что-нибудь надежно. Поймать RuntimeException и проверенные исключения, но не ошибки.
как правило, вы всегда должны поймать
java.lang.Errorи записать его в журнал или отображать его пользователю. Я работаю в Службе поддержки и ежедневно вижу, что программисты не могут сказать, что произошло в программе.если у вас есть поток демона, то вы должны предотвратить его прекращения. В других случаях ваше приложение будет работать правильно.
вы должны поймать только
java.lang.Errorна самом высоком уровне.если вы посмотрите на список ошибок, вы увидите, что большинство из них может быть обработан. Например,
ZipErrorпроисходит при чтении поврежденных zip-файлов.наиболее распространенными ошибками являются
OutOfMemoryErrorиNoClassDefFoundError, которые в большинстве случаев являются проблемами времени выполнения.например:
int length = Integer.parseInt(xyz); byte[] buffer = new byte[length];создать
OutOfMemoryErrorно это проблема runtime и нет причин, чтобы прекратить вашу программу.
NoClassDefFoundErrorвозникают в основном, если библиотека отсутствует или если вы работаете с другой версией Java. Если это необязательная часть программы, то вы не должны завершите свою программу.Я могу привести еще много примеров, почему это хорошая идея, чтобы поймать
Throwableна верхнем уровне и производить полезное сообщение об ошибке.
в многопоточной среде, вы чаще всего хотите, чтобы поймать его! Когда вы поймаете его, войдите в него и завершите все приложение! Если вы этого не сделаете, какой-то поток, который может выполнять какую-то важную часть, будет мертв, а остальная часть приложения будет думать, что все нормально. Из этого может произойти много нежелательных ситуаций. Одна из самых маленьких проблем заключается в том, что вы не сможете легко найти корень проблемы, если другие потоки начнут выбрасывать некоторые исключения из-за того, что один поток не рабочий.
например, обычно цикл должен быть:
try { while (shouldRun()) { doSomething(); } } catch (Throwable t) { log(t); stop(); System.exit(1); }даже в некоторых случаях вы хотели бы обрабатывать разные ошибки по-разному, например, на OutOfMemoryError вы могли бы регулярно закрывать приложение (даже, возможно, освободить некоторую память и продолжить), на некоторых других, вы не можете много сделать.
очень редко.
Я бы сказал только на верхнем уровне потока, чтобы попытаться выдать сообщение с причиной смерти Потока.
Если вы находитесь в рамках, которые делают такие вещи для вас, оставьте его в рамках.
почти никогда. Ошибки предназначены для проблем, с которыми приложения обычно ничего не могут поделать. Единственным исключением может быть обработка представления ошибки, но даже это может пойти не так, как планировалось в зависимости от ошибки.
An
ErrorКак правило, не должны быть пойманы, а это указывает на ненормальное состояние, которое никогда не должно возникать.из спецификации Java API для
Errorкласс:An
Errorявляется наследникомThrowableэто указывает на серьезные проблемы, что разумное применение не должно пытаться ловить. Большинство таких ошибок аномальные условия. [...]метод не требуется объявить в его бросает предложение любые подклассы Ошибка, которая может возникнуть во время выполнение метода, но не поймали, так как эти ошибки являются ненормальные условия, которые никогда не должны происходить.
как указано в спецификации,
Errorбросается только в обстоятельствах, которые являются Скорее всего, когдаErrorпроисходит, есть очень мало приложение может сделать, и в некоторых обстоятельствах, сама виртуальная машина Java может быть в нестабильном состоянии состояние (например,VirtualMachineError)хотя
Errorявляется наследникомThrowableчто означает, что он может быть пойманtry-catchпредложение, но это, вероятно, на самом деле не нужно, так как приложение будет находиться в ненормальном состоянии, когдаErrorбросается JVM.есть также небольшой раздел по этой теме В разделе 11.5 Иерархия Исключений на спецификация языка Java, 2-е издание.
Если вы достаточно сумасшедшие, чтобы создавать новую платформу модульного тестирования, ваш тестовый бегун, вероятно, должен будет поймать java.ленг.AssertionError выбрасывается любыми тестовыми случаями.
в противном случае см. другие ответы.
и есть еще несколько случаев, когда если вы поймаете ошибку, вы придется переосмыслить его. Например ThreadDeath никогда не должны быть пойманы, это может вызвать большую проблему, вы поймаете его в замкнутой среде (например. сервер приложений) :
приложение должно перехватывать экземпляры этого класса только в том случае, если оно должно очистить после завершения асинхронно. Если ThreadDeath пойман методом, Это важно чтобы он был перестроен так, чтобы нить действительно умирала.
очень, очень редко.
Я сделал это только для одного очень конкретные известные случаи. Например, java.ленг.UnsatisfiedLinkError можно бросить, если два загрузчика независимости загрузить ту же DLL. (Я согласен, что я должен переместить банку в общий загрузчик классов)
но наиболее распространенным случаем является то, что вам нужно войти в систему, чтобы знать, что произошло, когда пользователь пришел жаловаться. Вы хотите сообщение или всплывающее окно для пользователя, а затем тихо умер.
даже программист на C / C++, они выскакивают ошибку и говорят что-то, что люди не понимают до его выхода (например, сбой памяти).
в приложении для Android я ловлю java.ленг.VerifyError. Библиотека, которую я использую, не будет работать на устройствах со старой версией ОС, и код библиотеки выдаст такую ошибку. Я мог бы, конечно, избежать ошибки, проверив версию ОС во время выполнения, но:
- самый старый поддерживаемый SDK может измениться в будущем для конкретной библиотеки
- блок ошибок try-catch является частью большего механизма отката. Некоторые конкретные устройства, хотя они должны поддерживать библиотеку, выбрасывают исключения. Я ловлю VerifyError и все исключения для использования Резервного решения.
В идеале мы не должны обрабатывать/ловить ошибки. Но могут быть случаи, когда нам нужно это сделать, исходя из требований фреймворка или приложения. Скажем, у меня есть демон синтаксического анализа XML, который реализует DOM Parser который потребляет больше памяти. Если есть требование, как парсер поток не должен быть умер, когда он получает OutOfMemoryError, вместо этого он должен обработать его и отправить сообщение/письмо администратору приложения/фреймворка.
в идеале мы никогда не должны ловить ошибку в нашем приложении Java, поскольку это ненормальное состояние. Приложение будет находиться в ненормальном состоянии и может привести к carshing или давая какой-то серьезно неправильный результат.
может быть целесообразно поймать ошибку в модульных тестах, которые проверяют утверждение. Если кто-то отключает утверждения или иным образом удаляет утверждение, которое вы хотели бы знать
есть ошибка, когда JVM больше не работает, как ожидалось, или находится на грани. Если вы поймать ошибку, нет никакой гарантии, что блок catch будет работать, и даже меньше, что он будет работать до конца.
Это также будет зависеть от работающего компьютера, текущего состояния памяти, поэтому нет никакого способа проверить, попробовать и сделать все возможное. Вам останется только результат опасное.
вы также понизите читаемость вашего кода.
Comments