- •Содержание
- •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
Предпочитайте стандартные исключения
Одной из сильных сторон экспертов, отличающих их от менее опытных программистов, является то, что эксперты борются за высокую степень повторного использования программного когда и обычно этого добиваются. Общее правило, гласящее, что повторно используемый код - это хорошо, относится и к технологии исключении. В библиотеках для платформы Java реализован основной набор необрабатываемых исключений, перекрывающий большую часть потребностей в исключениях для API. В этой статье обсуждаются наиболее часто применяемые исключения.
Повторное использование уже имеющихся исключений имеет несколько преимуществ. Главное то, что они упрощают освоение и применение вашего API, поскольку соответствуют установленным соглашениям, с которыми программисты уже знакомы. С этим же связано второе преимущество, которое заключается в том, что программы, использующие ваш API, легче читать, поскольку там нет незнакомых, сбивающих с толку исключений. Наконец, чем меньше классов исключений, тем меньше требуется места в памяти и времени на их загрузку.
Чаще всего используется исключение IllegalArgumentException. Обычно оно инициируется, когда вызываемому методу передается аргумент с неправильным значением. Например, IllegalArgumentException может инициироваться в случае, если для параметра, указывающего количество повторов для некоей процедуры, передано Отрицательное значение.
Другое часто используемое исключение - IllegalStateException. Оно обычно инициируется, если в соответствии с состоянием объекта вызов метода является неправомерным. Например, это исключение может инициироваться, 'Когда делается попытка использовать некий объект до его инициализации надлежащим образом.
Вряд ли можно утверждать, что все неправильные вызовы методов сводятся к неправ ильным аргументам или неправильному состоянию, поскольку для определенных типов неправильных аргументов и состояний стандартно используются совсем другие
165
исключения. Если при вызове какому-либо параметру было передано null, тогда как значения null для него запрещены, то в этом случае в соответствии с соглашениями должно инициироваться исключение NullPointerException, а не IllegalArgumentException. Точно так же, если параметру, который соответствует индексу не коей последовательности, при вызове было передано значение, выходящее за границы допустимого диапазона, инициироваться должно исключение IndexOutOfBoundsException, а не IllegalArgumentException.
Еще одно универсальное исключение, о котором необходимо знать: ConcurrentModificationException. ()но должно инициироваться, когда объект, предназначавшийся для работы в одном потоке или с внешней синхронизацией, обнаруживает, что его изменяют (или изменили) из параллельного потока.
Последнее универсальное исключение, заслуживающее упоминания,- UnsupportedOperationException. ()но инициируется, если объект не имеет поддержки производимой операции. По сравнению с другими исключениями, обсуждавшимися в этой статье, UnsupportedOperationException применяется довольно редко, поскольку большинство объектов обеспечивает поддержку всех реализуемых ими методов. Это исключение используется при такой реализации интерфейса, когда отсутствует поддержка одной или нескольких заявленных в нем дополнительных функций. Например, реализация интерфейса List, имеющая только функцию добавления элементов, будет инициировать это исключение, если кто-то попытается удалить элемент.
В таблице 8.1 собраны самые распространенные из повторно используемых исключений.
Часто используемые исключения
Исключение |
Повод для использования |
IllegalArgumentException |
Неправильное значение параметра |
IllegalStateException |
Состояние объекта неприемлемо для вызова метода
|
NullPointerException |
Значение параметра равно null, а это запрещено |
IndexOutOfBoundsException |
Значение параметра, задающего индекс, выходит за пределы диапазона |
ConcurrentModificationException |
Обнаружена параллельная модификация объекта из разных потоков, а это запрещено
|
UnsupportedOperationException |
Объект не имеет поддержки указанного метода
|
|
|
Помимо перечисленных исключений, при определенных обстоятельствах могут применяться и другие исключения. Например, при реализации таких арифметических объектов, как комплексные числа и матрицы, уместно пользоваться исключениями ArithmeticException и NumberFormatException. Если исключение отвечает вашим
166
потребностям - пользуйтесь им, но только чтобы условия, при которых вы будете его инициировать, не вступали в противоречие с документацией к этому исключению. Выбирая исключение, следует исходить из его семантики, а не только из названия. Кроме того, если вы хотите дополнить имеющееся исключение информацией об отказе (статья 45), не стесняйтесь создавать для него подклассы.
И наконец, учитывайте, что выбор исключения - не всегда точная наука, поскольку "поводы для использования", приведенные в таблице 8.1, не являются взаимоисключающими. Рассмотрим, например, объект, соответствующий колоде карт. Предположим, что для него есть метод, осуществляющий выдачу карт из колоды, причем в качестве аргумента ему передается количество требуемых карт. Допустим, что при вызове с этим параметром было передано значение, превышающее количество карт, оставшихся в колоде. Эту ситуацию можно толковать как IllegalArgumentException (значение параметра "размер сдачи" слишком велико) либо как IllegalStateException (объект "колода" содержит слишком мало карт для обработки запроса). В данном случае, по-видимому, следует использовать IllegalArgumentException, но непреложных правил здесь не существует.