Тезисы Effective Java — Создание и уничтожение объектов

Создание и уничтожение объектов

1 Отдайте предпочтение статическим методам, а не конструкторам

  • Статические методы имеют имена
  • Статические методы не требуют создавать объекты на каждый вызов
  • Статические методы могут возвращать объекты подтипа
  • Статические методы сокращают параметризованные объявления
  • Помните, что классы только лишь со статическими методами создания,  без публичных или защищенных конструкторов не могут быть унаследованы
  • Статические методы для получения экземпляров объектов не отличимы от других статических методов, что может ухудшить читаемость кода

2 Отдайте предпочтение шаблону «Строитель», а не множеству конструкторов с опциональными параметрами

  • Телескопический конструктор тяжело использовать и тяжело читать код с множеством его параметров
  • Шаблон «JavaBean» допускает неконсистентность состояния во время конструирования
  • Шаблон «JavaBean» исключает возможность иммутабельности объектов
  • Шаблон «Строитель»  симулирует использование именованных опциональных параметров
  • Создание экземпляров выбрасывает исключения времени компиляции
  • Шаблон «Строитель» — отличный выбор, если конструкторы или статические фабрики объектов имеют множество параметров

3 Добейтесь использования класса как «Одиночки» при помощи закрытого конструктора или перечисления

  • Сделав класс «Одиночкой», вы усложняете тестирование кода, который его использует
  • Приватный конструктор может быть вызван через рефлексию, для защиты от таких атак требуется дополнительный счётчик экземпляров
  • Если ваш класс поддерживает сериализацию, не забудьте переопределить метод readResolve
  • Реализация «Одиночки» при помощи константного (final) поля позволяет улучшить читаемость кода, но снижает гибкость
  • Реализация «Одиночки» при помощи статического метода позволяет гибко менять источник получения экземпляра
  • «Одиночка» может быть реализован как единственный элемент перечисления, так мы получаем готовый к сериализации объект, устойчивый к атакам через рефлексию

4 Добейтесь запрета на создание экземпляров при помощи закрытого конструктора

  • Попытка добиться запрета на создание экземпляров при помощи модификатора abstract — не работает. Более того, это ложно сигнализирует о том, что класс разработан для наследования
  • Для запрета на создание экземпляров создайте закрытый конструктор. Дополнительно вы можете выбросить в нём исключение о невозможности создания экземпляра

5 Избегайте создания ненужных объектов

  • Не используйте конструкторы для упакованных версий примитивов и строк
  • Используйте статические методы valueOf для получения экземпляров примитивов из строк
  • Храните объекты, которые дорого создавать, если это возможно
  • Храните объекты эффективно, получая их экземпляры по требованию
  • Опасайтесь «автоупаковки» примитивов. Предпочитайте примитивы, а не их «упакованные» версии
  • Не используйте хранилища для маленьких и дёшево создаваемых объектов
  • Не используйте объект повторно, когда вам следует создать новый. Это прежде всего улучшает стиль и защищает от неприятных ошибок (например при защитном копировании)

6 Избавьтесь от ненужных ссылок на объекты

  • Обнуление ссылок на неиспользуемые объекты скорее исключение из правил, нежели норма
  • Когда бы класс ни использовал свою память, разработчик должен быть начеку относительно утечек памяти
  • Типичный источник утечек памяти — различного рода кэши
  • Один из источников утечек — «Слушатели» и «Обратные вызовы». Задумайтесь об использовании WeakReference или WeakHashMap

7 Избегайте финализаторов (finalizers)

  • Финализаторы непредсказуемы, зачастую опасны и обычно ненужны
  • Никогда не выполняйте в финализаторе действий, критичных по времени
  • Никогда не полагайтесь на финализатор для изменения критичного персистентного состояния
  • За использование финализатора вы платите дополнительным временем на его вызов
  • Предоставьте явный метод уничтожения объекта, вместо использования финализатора
  • Явные методы уничтожения обычно используются в паре с блоком try-finally
  • Финализатор должен вывести предупреждение о наличии неуничтоженных ресурсов
  • Не забудьте вызвать финализатор суперкласса в блоке finally
  • Используйте поле анонимного класса для реализации безопасного финализатора

 

Yuriy Artamonov on GithubYuriy Artamonov on LinkedinYuriy Artamonov on Twitter
Yuriy Artamonov
Software Developer
До последнего времени Юрий принимал активное участие в разработке опенсорс-фреймворка CUBA Platform, специализируясь на архитектуре и фронтенд-технологиях. Преподавал в Самарском университете разработку приложений для мобильных устройств, основы UI/UX и менторил студентов.

В настоящее время работает в компании JetBrains в команде IntelliJ IDEA Ultimate. Когда выдаётся свободное время, пишет статьи и контрибьютит в проекты с открытым исходным кодом. Обожает реализовывать странные идеи с лозунгом: «А почему бы и нет?».