Создание и уничтожение объектов
1 Отдайте предпочтение статическим методам, а не конструкторам
- Статические методы имеют имена
- Статические методы не требуют создавать объекты на каждый вызов
- Статические методы могут возвращать объекты подтипа
- Статические методы сокращают параметризованные объявления
- Помните, что классы только лишь со статическими методами создания, без публичных или защищенных конструкторов не могут быть унаследованы
- Статические методы для получения экземпляров объектов не отличимы от других статических методов, что может ухудшить читаемость кода
2 Отдайте предпочтение шаблону «Строитель», а не множеству конструкторов с опциональными параметрами
- Телескопический конструктор тяжело использовать и тяжело читать код с множеством его параметров
- Шаблон «JavaBean» допускает неконсистентность состояния во время конструирования
- Шаблон «JavaBean» исключает возможность иммутабельности объектов
- Шаблон «Строитель» симулирует использование именованных опциональных параметров
- Создание экземпляров выбрасывает исключения времени компиляции
- Шаблон «Строитель» — отличный выбор, если конструкторы или статические фабрики объектов имеют множество параметров
3 Добейтесь использования класса как «Одиночки» при помощи закрытого конструктора или перечисления
- Сделав класс «Одиночкой», вы усложняете тестирование кода, который его использует
- Приватный конструктор может быть вызван через рефлексию, для защиты от таких атак требуется дополнительный счётчик экземпляров
- Если ваш класс поддерживает сериализацию, не забудьте переопределить метод readResolve
- Реализация «Одиночки» при помощи константного (final) поля позволяет улучшить читаемость кода, но снижает гибкость
- Реализация «Одиночки» при помощи статического метода позволяет гибко менять источник получения экземпляра
- «Одиночка» может быть реализован как единственный элемент перечисления, так мы получаем готовый к сериализации объект, устойчивый к атакам через рефлексию
4 Добейтесь запрета на создание экземпляров при помощи закрытого конструктора
- Попытка добиться запрета на создание экземпляров при помощи модификатора abstract — не работает. Более того, это ложно сигнализирует о том, что класс разработан для наследования
- Для запрета на создание экземпляров создайте закрытый конструктор. Дополнительно вы можете выбросить в нём исключение о невозможности создания экземпляра
5 Избегайте создания ненужных объектов
- Не используйте конструкторы для упакованных версий примитивов и строк
- Используйте статические методы valueOf для получения экземпляров примитивов из строк
- Храните объекты, которые дорого создавать, если это возможно
- Храните объекты эффективно, получая их экземпляры по требованию
- Опасайтесь «автоупаковки» примитивов. Предпочитайте примитивы, а не их «упакованные» версии
- Не используйте хранилища для маленьких и дёшево создаваемых объектов
- Не используйте объект повторно, когда вам следует создать новый. Это прежде всего улучшает стиль и защищает от неприятных ошибок (например при защитном копировании)
6 Избавьтесь от ненужных ссылок на объекты
- Обнуление ссылок на неиспользуемые объекты скорее исключение из правил, нежели норма
- Когда бы класс ни использовал свою память, разработчик должен быть начеку относительно утечек памяти
- Типичный источник утечек памяти — различного рода кэши
- Один из источников утечек — «Слушатели» и «Обратные вызовы». Задумайтесь об использовании WeakReference или WeakHashMap
7 Избегайте финализаторов (finalizers)
- Финализаторы непредсказуемы, зачастую опасны и обычно ненужны
- Никогда не выполняйте в финализаторе действий, критичных по времени
- Никогда не полагайтесь на финализатор для изменения критичного персистентного состояния
- За использование финализатора вы платите дополнительным временем на его вызов
- Предоставьте явный метод уничтожения объекта, вместо использования финализатора
- Явные методы уничтожения обычно используются в паре с блоком try-finally
- Финализатор должен вывести предупреждение о наличии неуничтоженных ресурсов
- Не забудьте вызвать финализатор суперкласса в блоке finally
- Используйте поле анонимного класса для реализации безопасного финализатора