- •Содержание
- •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
Возвращайте массив нулевой длины, а не null
Нередко встречаются методы, имеющие следующий вид:
private List cheesesInStock = ... ;
/**
* @return массив, содержащий все сыры, имеющиеся в магазине,
* или null, если сыров для продажи нет.
*/
public Cheese[] getCheeses() {
if (cheesesInStock.size() == 0)
return null;
}
125
Нет причин рассматривать как особый случай ситуацию, когда в продаже нет сыра. Это требует от клиента написания дополнительного кода для обработки возвращаемого методом значения пull, например:
Cheese[] cheeses = shop.getCheeses();
if (cheeses ! = пull &&
Аrrауs.аsList(shор.gеtСhееsеs()).соntаins(Сhееsе.SТILТON))
Sуstеm.оut.рrintln("Jоllу good, just the thing.");
вместо простого:
if (Аrrаys.аsList(shор.gеtСhееsеs()).соntаins(Сhееsе.SТILTON)) Sуstеm.оut.рrintln("Jоllу good, just the thing.");
Такого рода многоречивость необходима почти при каждом вызове метода, который BM~CTO массива нулевой длины возвращает null. Это чревато ошибками, так как разработчик клиента мог и не написать специальный код для обработки результата null. Ошибка может оставаться незамеченной годами, поскольку подобные методы, как правило, возвращают один или несколько объектов. Следует еще упомянуть о том, что возврат null вместо массива приводит к усложнению самого метода, возвращающего массив.
Иногда можно услышать возражения, что возврат значения null предпочтительнее возврата массива нулевой длины потому, что это позволяет избежать расходов на размещение массива в памяти. Этот аргумент несостоятелен по двум причинам. Во-первых, на этом уровне нет смысла беспокоиться о производительности, если только профилирование программы не покажет, что именно этот метод является основной причиной падения производительности (статья 37). Во-вторых, при каждом вызове метода, который не возвращает записей, клиенту можно передавать один и тот же массив нулевой длины, поскольку любой массив нулевой длины неизменяем, а неизменяемые объекты доступны для совместного использования (статья 13). На самом деле, именно это и происходит, когда вы применяете стандартную идиому для выгрузки элементов из коллекции в массив с контролем типа:
private List сhееsеsInStосk = ... ,
private fiпаl static Cheese[] NULL_CHEESE_ARRAY = nеw Cheese[0];
/**
* @геtuгп массие, содержащий все сыры, имеющиеся в магазине
*/
public Cheese[] getCheeses() {
геtuгп (Cheese[] сhееsеsInStосk.tоАггау(NULL_СНЕЕSЕ_АRRАУ); }
В этой идиоме константа в виде массива нулевой длины передается методу toArray для того, чтобы показать, какой тип он должен возвратить. Обычно метод toArray выделяет место в памяти для возвращаемого массива, однако если коллекция пуста,
126
она размещается во входном массиве, а спецификация Сollесtion,tоАггау(ОЬjесt[] дает гарантию, что если входной' массив будет достаточно вместителен, чтобы содержать коллекцию, возвращен будет именно он. Поэтому представленная идиома никогда не будет сама размещать в памяти массив нулевой длины, а в качестве такового использует "константу с указанием типа".
Подведем итоги. Нет никаких причин для того, чтобы работающий с массивами метод возвращал значение null, а не массив нулевой длины. Такая идиома, по-видимому, проистекает из языка программирования С, где длина массива возвращается отдельно от самого массива. В языке С бесполезно выделять память под массив нулевой длины.