- •Содержание
- •1. Введение
- •2. Создание и уничтожение объектов
- •3. Методы, общие для всех объектов
- •4. Классы и интерфейсы
- •5. Замена конструкций на языке c
- •6. Методы
- •7. Общие вопросы программирования
- •8. Исключения
- •9. Потоки
- •10. Сериализация
- •11. Литература
- •Глава 1
- •Глава 2 Создание и уничтожение объектов
- •Рассмотрите возможность замены конструкторов статическими методами генерации.
- •Свойство синглтона обеспечивайте закрытым конструктором
- •Отсутствие экземпляров обеспечивает закрытый конструктор
- •Не создавайте дублирующих объектов
- •Уничтожайте устаревшие ссыпки (на объекты)
- •Остерегайтесь методов flnalize
- •Глава 3 Методы, общие для всех объектов
- •Переопределяя метод equals, соблюдайте общие соглашения
- •Переопределяя метод equals, всегда переопределяйте hashCode
- •Всегда переопределяйте метод toStrlng
- •Подумайте над реализацией интерфейса ComparabIe
- •Глава 4 Классы и интерфейсы
- •Сводите к минимуму доступность классов и членов
- •Предпочитайте постоянство
- •Предпочитайте компоновку наследованию
- •Предпочитайте интерфейсы абстрактным классам.
- •Используйте интерфейсы только для определения типов
- •Предпочитайте статические классы-члены нестатическим
- •Глава 5
- •3Амена констрvкций на языке с
- •3Аменяйте структуру классом
- •3Амеияйте объедииеиие иерархией классов
- •/* Помещает данные в одно из полей объединения ... */
- •3Аменяйте конструкцию enum классом
- •Указатель на функцию заменяйте кпассом и интерфейсом
- •Глава 6 Методы
- •Проверяйте достоверность параметров
- •При необходимости создавайте резервные копии
- •Тщательно проектируйте сигнатуру метода
- •Перегружая методы, соблюдайте осторожность
- •Возвращайте массив нулевой длины, а не null
- •Для всех открытых элементов арi пишите dос - комментарии
- •Глава 7 Общие вопросы программирования
- •Сводите к минимуму область видимости локальных переменных
- •Изучите библиотеки и пользуйтесь ими
- •Не используйте строку там, где более уместен иной тип
- •При конкатенации строк опасайтесь потери производительности
- •Для ссыпки на объект используйте его интерфейс
- •Соблюдайте осторожность при использовании машинно-зависимых методов
- •Соблюдайте осторожность при оптимизации
- •Глава 8 Исключения
- •Используйте исключения лишь в исключительных ситуациях
- •Применяйте обрабатываемые исключения для восстановления, для программных ошибок используйте исключения времени выполнения
- •Избегайте ненужных обрабатываемых исключений
- •Предпочитайте стандартные исключения
- •Инициируйте исключения, соответствующие абстракции
- •Для каждого метода документируйте все инициируемые исключения
- •В описание исключения добавляйте информацию о сбое
- •Добивайтесь атомарности методов по отношению к сбоям
- •Не игнорируйте исключений
- •Глава 9 Потоки
- •Синхронизируйте доступ потоков к совместно используемым изменяемым данным
- •Избегайте избыточной синхронизации
- •Никогда не вызывайте метод wait вне цикла
- •Не попадайте в зависимость от планировщика потоков
- •При работе с потоками документируйте уровень безопасности
- •Избегайте группировки потоков
- •Глава 10 Сериализация
- •Соблюдайте осторожность при реализации интерфейса SerializabIe
- •Рассмотрите возможность использования специализированной сериализованной формы
- •Метод readObject должен создаваться с защитой
- •При необходимости создавайте метод readResolue
Инициируйте исключения, соответствующие абстракции
Если метод инициирует исключение, не имеющее видимой связи с решаемой задачей, это сбивает с толку. Часто это происходит, когда метод передает исключение, инициированное абстракцией нижнего уровня. Это не только приводит в замешательство, но и засоряет интерфейс верхнего уровня деталями реализации. Если в следующей версии реализация верхнего уровня поменяется, то также могут поменяться и инициируемые им исключения, в результате чего могут перестать работать имеющиеся клиентские программы.
Во избежание этой проблемы верхние уровни приложения должны перехватывать исключения нижних уровней и, в свою очередь, инициировать исключения, которые можно объяснить в терминах абстракции верхнего уровня. Описываемая идиома, которую мы называем трансляцией исключении. (exception translation), выглядит следующим образом:
// Трансляция исключения
try {
// Использование абстракции нижнего уровня
// для выполнения наших указаний
} catch(LowerLevelException е) {
throw new HigherLevelException( ... ); }
167
Приведем конкретный пример трансляции исключения, взятый из класса AbstractSequentialList, который представляет собой скелетную реализацию (статья 16) интерфейса List. В этом примере трансляция исключения продиктована спецификацией метода get в интерфейсе List:
/**
* Возвращает элемент, находящийся в указанной позиции
* в заданном списке.
* @throws IndexOutOfBoundsException, если индекс находится
* за пределами диапазона (index < 0 II index >= size()).
*/
public Object get(int index) {
ListIterator i = listItеrаtor(index);
try {
return i. next();
catch (NoSuchElementException е) {
throw new IndexOutOfBoundsException("Index: " + index); }
}
В тех случаях, когда исключение нижнего уровня может быть полезно при анализе ситуации, вызвавшей исключение, лучше использовать особый вид трансляции исключений, называемый сцеплением исключении (exception chaining). При этом исключение нижнего уровня передается с исключением верхнего уровня; в последнем создается открытый метод доступа, позволяющий извлечь исключение нижнего уровня:
// Сцепление исключений
try {
// Использование абстракции нижнего уровня
// для выполнения наших указаний
} catch(LowerLevelException е) {
throw new H1gherLevelException(e); }
в версии 1.4 сцепление исключений поддерживается классом Throwable. В этой и последующих версиях можно использовать преимущества такой поддержки, связав ваш конструктор исключения верхнего уровня с конструктором Throwable(Throwable):
// Сцепление исключений в версии 1.4
HigherLevelException(Throwable t) {
super(t); }
168
Если же вы используете более раннюю версию, ваше исключение должно само сохранять исключение нижнего уровня и предоставлять соответствующий метод доступа:
// Сцепление исключений в версии, предшествующей 1.4
private Throwable cause;
НighегLеvеlЕхсерtiоп(Тhгоwаblе t) {
cause = t; }
public Throwable getCause() {
return cause; }
Дав методу доступа название getCause и применив указанную декларацию, вы получите гарантию того, что ваше исключение будет взаимодействовать с механизмом сцепления исключений для данной платформы так, как если бы вы использовали исключение в версии 1.4. Это дает то преимущество, что в исключение верхнего уровня стандартным образом будет интегрирована трассировка стека для исключения нижнего уровня. Кроме того, это позволяет задействовать стандартные средства отладки для доступа к исключению нижнего уровня.
Хотя трансляция исключений лучше, чем бессмысленная передача исключений с нижних уровней, злоупотреблять ею не следует. Самый хороши" способ обработки исключений нижнего уровня - полностью исключить их возможность. Для этого перед выбором метода нижнего уровня необходимо убедиться в том, что он будет выполнен успешно, иногда добиться этого можно путем явной проверки аргументов метода верхнего уровня перед их передачей на нижний уровень.
Если предупредить появление исключений на нижних уровнях невозможно, то лучшее решение состоит в том, чтобы верхний уровень молча обрабатывал эти исключения, изолируя клиента от проблем нижнего уровня. В таких условиях чаще всего достаточно протоколировать исключения, используя какой-либо механизм регистрации, например java,util,logging, появившийся в версии 1.4. Это дает возможность администратору исследовать возникшую проблему и в то же время изолирует от нее программный код клиента и конечного пользователя.
В ситуациях, когда невозможно предотвратить возникновение исключений на нижних уровнях или изолировать от них верхние уровни, как правило, должен применяться механизм трансляции исключений. Непосредственную передачу исключений с нижележащего уровня на верхний следует разрешать только тогда, когда, исходя из описания метода на нижнем уровне, можно дать гарантию, что все инициируемые им исключения будут приемлемы для абстракции верхнего уровня.
169