Захват ошибок Java
Я слышал, что ловить java.lang.Error
считается плохой практикой.
Я в настоящее время загружаю .dll, который не гарантируется в PATH, и хотел бы переключиться на настроенное пользователем местоположение в случае, если это не так.
try {
System.loadLibrary("HelloWorld");
} catch(UnsatisfiedLinkError ule){
System.load("C:/libraries/HelloWorld.dll");
}
Есть ли лучший способ сделать это? Или ловить UnsatisfiedLinkError
здесь приемлемо?
Ответы
Ответ 1
Помимо предоставления рекомендаций о том, как технически преодолеть эту проблему, я хотел бы остановиться и объяснить, почему в первую очередь это считается "плохой практикой".
Пусть начнется, уточнив класс Error
.
В java генерируются ошибки и исключения (которые являются основными типами). Выбрасывание одного из указанных выше выполняется с помощью ключевого слова throw
. Каждый класс, который расширяет базовый java.lang.Throwable
, может быть брошен.
Существует два класса, которые наследуют базовый класс Throwable
: Exception
и Error
. Разница между этими двумя объясняется в их документах:
Ошибка - это подкласс Throwable, который указывает на серьезный проблемы, которые разумное приложение не должно пытаться поймать. Наиболее такие ошибки являются ненормальными условиями. [...]
Источник
Класс Exception и его подклассы являются формой Throwable что указывает условия, которые может потребовать разумное приложение ловить.
Источник
Как объяснялось выше, ошибки и исключения разделяются из-за их различного происхождения. Error
обычно указывает на проблему, от которой приложение не может восстановиться. Поэтому их не следует улавливать.
То же самое верно для RuntimeException
, но оно используется для указания проблемы с уровнем высокого уровня (например, методы). В то время как Error
указывает проблему низкого уровня (например, время выполнения).
Итак, теперь, когда вы поняли, что вы должны обрабатывать исключения и ошибки, которые вы можете восстановить из, ответ на ваш вопрос должен быть ясным.
Да, вполне разумно поймать UnsatisfiedLinkError
, потому что ваше приложение может восстановить его.
Я рассмотрел выше (более подробно и с примерами) и некоторую расширенную информацию в статье в моем блоге.
Ответ 2
loadLibrary вызывает findLibrary(), который был бы полезен, но он был защищен, лучше всего написать собственный класс, расширяющий ClassLoader. У загрузчика классов есть защищенный метод, называемый findLibrary(), который вернет путь к библиотеке или null, если он не существует. Таким образом, вы можете просто проверить нуль, а не ловить ошибки. Я не уверен, что это на самом деле "лучше", но это избавит вас от необходимости попробовать catch;
Ответ 3
Если вы защищаете код и можете восстановить его из проблемы, то это не Java Error
. Если такая проблема не очень вероятна, создайте подкласс Exception
и бросьте и поймите. Если такая проблема вероятна, то она не должна даже бросать Exception
; но должен быть частью обычного потока кода.
try {
if (config.hasCustomDLL()) {
System.load(config.getCustomDLL());
} else {
System.loadLibrary(Config.DEFAULT_DLL);
}
} catch (UnstatisfiedLinkError e) {
System.out.println("Error loading DLL: " + e);
}
Errors
предназначены для действительно плохих сбоев, а не для восстановления "сбоев", которые действительно не являются даже отказами, если есть подходящее обходное решение. Не перегружайте систему, предназначенную для устранения сбоя, и это означает возможность настройки системы несколькими способами.
Ответ 4
Вы должны улавливать ошибки только в особых случаях. Только улов и ошибка, если вы изучили все другие возможности. Я полностью согласен со всем, что сказал Лукас Кнут. Но у меня есть одно небольшое дополнение.
Если вы поймаете какую-либо ошибку, убедитесь, что вы улавливаете ошибки как можно более узкие. Кроме того, если это возможно, убедитесь, что методы, по которым вы обнаруживаете ошибки, объявляются окончательными. Причина в том, что улавливающие ошибки обычно приводят к некоторым очень шатким программам. Подумайте, что вы поймаете ошибку в методе, который позже расширен для вызова других методов, все эти базовые методы теперь также будут иметь ошибки, которые были бы уловлены (непреднамеренно) с помощью вышележащего улова.
Если вам нужно поймать ошибку, сделайте это в узком, контролируемом fasion.