Главная » Java, Советы » Избегайте ненужных обрабатываемых исключений

0

 

Обрабатываемые исключения -‘ замечательная особенность языка программирования Java. В отличие от возвращаемых кодов, они заставляют программиста отслеживать условия возникновения исключений, что значительно повышает надежность приложения. Это означает, что злоупотребление обрабатываемыми исключениями может сделать API менее удобным для использования. Если метод инициирует одно или несколько обрабатываемых исключений, то в программном коде, из которого этот метод был вызван, должна присутствовать обработка этих исключений в виде одного или нескольких блоков catch, либо должно быть декларировано, что этот код сам инициирует исключения и передает их дальше. В любом случае перед программистом стоит нелегкая задача.

Такое решение оправданно, если даже при надлежащем применении интерфейса API невозможно предотвратить возникновение условий для исключительной ситуации, однако программист, пользующийся данным API, столкнувшись с этим исключением, мог бы предпринять какие-либо полезные действия. Если не выполняются оба этих условия, лучше пользоваться необрабатываемым исключением. Роль лакмусовой бумажки в данном случае играет вопрос: как программист будет обрабатывать исключение? Является ли это решение лучшим:

 

} catch(TheCheckedException е) {

throw new Error("Assertion error");

// Условие не выполнено. Этого не должно быть никогда! 

}

 

А что скажете об этом:

 

} catch(TheCheckedException e) {

e.printStackTrace();                     //Ладно, закончили работу.

System. exit( 1);  }

 

Если программист, применяющий API, не может сделать ничего лучшего, то больше подходит необрабатываемое исключение. Примером исключения, не выдерживающего подобной проверки, является CloneNotSupportedException. Оно инициируется

методом Object. сlоnе, который должен использоваться лишь для объектов, реализующих интерфейс Cloneable (статья 10). Блок catch практически всегда соответствует невыполнению утверждения. Так что обрабатываемое исключение не дает программисту преимуществ, но требует от последнего дополнительных усилий и усложняет программу.

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

Один из приемов, позволяющих превратить обрабатываемое исключение в необрабатываемое, состоит в раз биении метода, инициирующего исключение, на два метода, первый из которых будет возвращать булево значение, указывающее, будет ли инициироваться исключение. Таким образом, в результате преобразования АРI последовательность вызова

 

// Вызов с обрабатываемым исключением

try {

obj.action(args);

catch(TheCheckedException е) {

// Обработать исключительную ситуацию

}

 

принимает следующий вид:

 

// Вызов с использованием метода проверки состояния

// и необрабатываемого исключения

if (obj.actionPermitted(args)) {

obj.action(args); }

else{ }

// Обработать исключительную ситуацию

 

Такое преобразование можно использовать не всегда, Если же оно допустимо, это может сделать работу с АРI более удобной. Хотя второй вариант последовательности вызова выглядит не лучше первого, полученный АРI имеет большую гибкость, В ситуации, когда программист знает, что вызов будет успешным, или согласен на завершение потока в случае неудачного вызова, преобразованный АРI позволяет использовать следующую упрощенную последовательность вызова:

 

obj,aotion(args):

 

Если вы предполагаете, что применение упрощенной последовательности вызова будет нормой, то описанное преобразование АР! приемлемо. API, полученный в результате этого преобразования, в сущности, тот же самый, что и АР! с методом "проверки состояния" (статья 39). Следовательно, к нему относятся те же самые предупреждения: если к объекту одновременно и без внешней синхронизации могут иметь доступ сразу несколько потоков или этот объект может менять свое состояние по команде извне, указанное преобразование использовать не рекомендуется. Это связано с тем, что в промежутке между вызовом actionPermitted и вызовом action состояние объекта может успеть поменяться. Если метод actionPermitted при необходимости и мог бы дублировать работу метода action, то от преобразования, вероятно, стоит отказаться по соображениям производительности.

 

Источник: Джошуа Блох, Java TM Эффективное программирование, Издательство «Лори»

По теме:

  • Комментарии