2.12. Неизменяемость

Итак, объявление полей как неизменяемых (final) может быть полезно. К тому же, неизменяемые методы тоже хороши. Отсюда можно сделать вывод, что классы, в которых все методы и поля неизменяемые, менее подвержены ошибкам.

В этом случае говорят о неизменяемых объектах [12].

Неизменяемые объекты хороши в первую очередь тем, что их поведение проще реализовывать, проще соблюдать корректность. К тому же, их данные можно относительно безбоязненно кэшировать.

В стандартной библиотеке Java классы-значения являются неизменяемыми (например, Integer и String). Это дает возможность легко кэшировать объекты класса Integer и возвращать один и тот же объект многократно из метода Integer.valueOf(). Поэтому не стоит вызывать конструктор класса Integer напрямую.

Неизменяемые объекты полезны при реализации перечислений [12].

Если все поля объявлены как final, это еще не значит, что объекты будут неизменяемыми. Если объект хранит ссылку на изменяемый объект и возвращает ее клиентам, то эти клиенты могут изменить состояние изменяемого объекта, а как следствие, изменится и состояние «неизменяемого».

Таких случаев возникает много. Особенно часто они встречаются при использовании коллекций и массивов. Поэтому возвращая наружу коллекцию, стоит «завернуть» ее с помощью метода Collections.unmodifiableCollection().

Возвращая массив, как и любой другой изменяемый объект, его нужно клонировать.

Другой случай потери неизменяемости — получение изменяемого объекта извне. Пусть хранится ссылка на изменяемый объект, но никому не предоставляется. Необходимо подумать, откуда взялся этот объект. Если он создан разработчиком, то нет проблем, но если он пришел от клиента, то клиент может хранить на него ссылку и изменять объект.

Получая изменяемые объекты от клиентов, сохраняйте не сами эти объекты, а их копии.