Posted on Leave a comment

Joshua Bloch – Effective Java

Create and destroy object

Рассмотрите возможность замены конструкторов
статическими методами генерации.

Свойство синглтона oбеспечивайте закрытым конструктором

Отсутствие экземпляров  обеспечивает закрытый конструктор

Не создавайте дублирующих объектов

Уничтожайте устаревшие ссылки (на объекты )

Остерегайтесь методов finalize

Методы, общие для вcех объектов

методы без модификатора final – equals, hashCode, toString, clone и finalize

Переопределяя метод equals, соблюдайте общие соглашения

Переопределяя метод equals, вы должны твердо придерживаться принятых для него общих
соглашений. Воспроизведем эти соглашения по тексту спецификации java,lang.Object:
Метод equals реализует отношение эквивалентности:
· Рефлективность, для любой ссылки на значение х выражение
х.equals(x) должно возвращать true.
· Симметричность, для любых ссылок на значения х и у
выражение х. equals(y) должно возвращать t гue тогда и только тогда, когда y.equals(x)
возвращает true.
· Транзитивность, для любых ссылок на значения х, у и z,
если x.equals(y) возвращает true и y.equals(z) возвращает true, то и выражение х.
equals(z) должно возвращать true.
· Непротиворечивость. Для любых ссылок на значения х и у,
если несколько раз вызвать х. equals(y), постоянно будет возвращаться значение true либо
постоянно будет возвращаться значение false при условии, что никакая информация,
используемая при сравнении объектов, не поменялась.
· Для любой ненулевой ссылки на значение х выражение х. equals(null) должно возвращать
false.

Переопределяя метод equals, всегда переопределяйте hashCode

Приведем текст соглашений, представленных в спецификации jауа.lang.Object:
· Если во время работы приложения несколько раз обратиться к одному и тому же объекту,
метод hashCode должен постоянно возвращать одно и то же целое число, показывая тем
самым, что информация, которая используется при сравнении этого объекта с другими
(метод equals), не поменялась. Однако если приложение остановить и запустить снова, это
число может стать другим.
· Если метод equals(Object) показывает, что два объекта равны друг другу, то вызвав для каждого
из них метод hashCode, вы должны получить в обоих случаях одно и то же целое число.
· Если метод equals(Object) показывает, что два объекта не равны
друг другу, вовсе не обязательно, что метод hashCode возвратит для них разные числа. Между
тем программист должен понимать, что генерация разных чисел для неравных объектов может
повысить эффективность хэш-таблиц.

Всегда переопределяйте метод toString

Соблюдайте осторожность при переопределении метода Сlоne

Подумайте над реализацией интерфейса ComparabIe

Классы и интерфейсы

Сводите к минимуму доступность классов и членов

Для членов класса (полей, методов, вложенных классов и вложенных интерфейсов) существуют
четыре возможных уровня доступа, которые перечислены здесь в порядке увеличения доступности:
· Закрытый (private) - данный член доступен лишь в пределах того класса верхнего уровня,
где он был объявлен.
58
· Доступный лишь в пределах пакета (package-private) - член доступен из любого класса в
пределах того пакета, где он был объявлен. Формально этот уровень называется
доступом по умолчанию
(default access), и именно этот уровень доступа вы получаете,
если не -были указаны модификаторы доступа.
· Защищенный (protected) - член доступен для подклассов того класса, "где этот член был
объявлен (с небольшими ограничениями [jLS, 6.6.2]); доступ к члену можно получить из
любого класса в пакете, где этот член был объявлен.
· Открытый (public) - член доступен отовсюду.

Предпочитайте постоянство

Делая класс неизменяемым, выполняйте следующие пять правил:
1. Не создавайте каких-либо методов, которые модифицируют представленный объект
(эти методы называются мутаторами (mutator)).
2. Убедитесь в том, что ни один метод класса не может быть переопределен. Это предотвратит
потерю свойства неизменяемости данного класса в небрежном или умышленно плохо
написанном подклассе. Защита методов от переопределения обычно осуществляется путем
объявления класса в качестве окончательного, однако есть
и другие способы (см. ниже).
3. Сделайте все поля окончательными (final). Это ясно выразит
ваши намерения, причем в некоторой степени их будет поддерживать сама система. Это
может понадобиться и для обеспечения правильного поведения программы в том случае,
когда ссылка на вновь созданный экземпляр передается из одного потока в другой без
выполнения синхронизации [Pugh01a] (как результат ведущихся работ
по ис~равлению модели памяти в ]ауа).
4. Сделайте все поля закрытыми (private). Это не позволит клиентам непосредственно менять
значение полей. Хотя формально неизменяемые классы и могут иметь открытые поля с
модификатором final, которые содержат либо значения простого типа, либо ссылки на
неизменяемые объекты, делать это не рекомендуется, поскольку они будут препятствовать
изменению в последующих версиях внутреннего представления класса (статья 12).
5. Убедитесь в монопольном доступе ко всем изменяемым компонентам. Если в вашем классе
есть какие-либо поля, содержащие ссылки на изменяемые объекты, удостоверьтесь в том, что
клиенты этого класса не смогут получить ссылок на эти объекты. Никогда не инициализируйте
такое поле ссылкой на объект, полученной от клиента, метод доступа не должен возвращать
хранящейся в этом поле ссылки на объект. При использовании конструкторов, методов доступа
к полям и методов readObject (статья 56) создавайте резервные копии (defensive copies) (статья
24).

Предпочитайте компоновку наследованию

Документируйте наследование

Предпочитайте интерфейсы абстрактным классам

Используйте интерфейсы только для определения типов

Предпочитайте статические классы-члены нестатическим

Замена конструкций на языке C

Заменяйте структуру классом

Заменяйте объединение иерархией классов

Заменяйте конструкцию enum классом

Указатель на функцию заменяйте классом и интерфейсом

Методы

Проверяйте достоверность параметров

При необходимости создавайте резервные копии

Тщательно проектируйте сигнатуру метода

Перегружая методы, соблюдайте осторожность

Возвращайте массив нулевой длины, а не null

Для всех открытых элементов АРI пишите dос-комментарии

Общие вопросы программирования

Сводите к минимуму область видимости локальных переменных

Изучите библиотеки и пользуйтесь ими

Если требуются точные ответы, избегайте использования типов float и doubIe

Не используйте строку там, где более уместен иной тип

При конкатенации строк опасайтесь потери производительности

Для ссылки на объект используйте его интерфейс

Предпочитайте интерфейс отражению класса

Соблюдайте осторожность при использовании машинно-зависимых
методов

Соблюдайте осторожность при оптимизации

Во имя эффективности (без обязательности ее достижения) делается больше
вычислительных ошибок, чем по каким-либо иным причинам, включая непроходимую
тупость.
- Уильям Вульф (William А. Wulf) [Wulf72]
Мы обязаны забывать о мелких усовершенствованиях, скажем, на 97 %
рабочего времени: опрометчивая оптимизация - корень всех зол.
- Дональд Кнут (Donald Е. Knuth) [Knuth74]
Что касается оптимизации, то мы следуем двум правилам:
Правило 1. Не делайте этого.
Правило 2 (только для экспертов). Пока не делайте этого - т. е. нет пока у вас абсолютно
четкого, но неоптимизированного решения.
- М. А. Джексон (М. А. Jackson) {fackson75]

При выборе имен придерживайтесь общепринятых соглашений

Исключения

Используйте исключения лишь в исключительных ситуациях

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

в языке программирования Java предусмотрены
три типа объектов Throwable:
обрабатываемые исключения (checked exception),
исключения времени выполнения (rиn-time exception)
и ошибки (error).

Избегайте ненужных обрабатываемых исключений

Предпочитайте стандартные исключения

Инициируйте исключения, соответствующие абстракции

Для каждого метода документируйте все инициируемые
исключения

В описание исключения добавляйте информацию о сбое

Добивайтесь атомарности методов по отношению к сбоям

Не игнорируйте исключений

Потоки

Синхронизируйте доступ потоков к совместно используемым изменяемым данным

Избегайте избыточной синхронизации

Никогда не вызывайте метод wait вне цикла

Не попадайте в зависимость от планировщика потоков

При работе с потоками документируйте уровень безопасности

* Неизменяемый (immutable). Экземпляры такого
класса выглядят для своих клиентов как
константы. Никакой внешней синхронизации
не требуется. Примерами являются String,
Integer и Biglnteger (статья 13).
* С поддержкой многопоточности (thread-safe).
Экземпляры такого класса могут изменяться,
однако все методы имеют довольно надежную
внутреннюю синхронизацию, чтобы эти
экземпляры могли параллельно использовать несколько
потоков безо всякой внешней
синхронизации. Параллельные вызовы будут обрабатываться
последовательно внекотором
глобально согласованном порядке.
Примеры: Random и java. util.Тimer.
* С условной поддержкой многопоточности
(conditionally thread-safe). т о же, что и с
поддержкой многопоточности, за исключением того,
что класс (или ассоциированный
класс) содержит методы, которые должны вызываться 
один за другим без взаимного
влияния со стороны других потоков. Для исключения возможности 
такого влияния клиент
должен установить соответствующую блокировку на время 
выполнения этой
последовательности. Примеры: Hashtable и Vector, чьи 
итераторы требуют внешней
синхронизации.
* Совместимый с многопоточностью (thread-compatible). 
Экземпляры такого класса можно
безопасно использовать при работе с параллельными потоками, 
если каждый вызов метода (а
в некоторых случаях, каждую последовательность вызовов) 
окружить внешней синхронизацией.
Примерами являются реализации коллекций общего назначения, 
такие как ArrayList и HashMap.
* Несовместимый с многопоточностью (thread-hostile). Этот класс 
небезопасен при параллельной
работе с несколькими потоками, даже если вызовы всех методов 
окружены внешней
синхронизацией. Обычно несовместимость связана с тем 
обстоятельством, что эти методы
меняют некие статические данные, которые оказывают влияние 
на другие потоки. К счастью,
в библиотеках платформы Java лишь очень немногие классы и 
методы несовместимы с
многопоточностью. Так, метод System.runFinalizersOnExit 
несовместим с многопоточностью и
признан устаревшим.

Избегайте группировки потоков

Сериализация

Соблюдайте осторожность при реализации интерфейса
SerializabIe

private static final long serialVersionUID

Рассмотрите возможность использования специализированной
сериализованной формы

Метод readObject должен создаваться с защитой

При необходимости создавайте метод readResolve

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.