Если вы хотите, чтобы ваш класс был неизменным (т. Е. Имел только final
поля и получатели), вы должны быть уверены, что возвращаемые значения также являются неизменяемыми.Вы получаете это бесплатно при возврате строк и встроенных примитивов, однако для других типов данных необходимы некоторые дополнительные шаги:
- обернуть коллекции неизменяемыми декораторами или скопировать их с защитой перед возвратом из получателя
- делает копии
Date
и Calendar
- Возвращает только неизменные объекты или
clone
для защиты.Это также относится к объектам в коллекциях.
Обратите внимание: если вы копируете коллекцию для защиты, клиент может просматривать или изменять копию, но это не влияет на исходную коллекцию:
return new ArrayList<Foo>(foos);
С другой стороны, если вы оберните исходную коллекцию, клиент сможет увидеть все изменения, которые были внесены в коллекцию после создания оболочки, но попытка изменить содержимое оболочки приведет к исключению времени выполнения:
return Collections.unmodifiableList(foos);
Суть в том, что Foo
также должен быть неизменным, в противном случае коллекция является неизменной, но клиентский код все еще может изменять членов коллекции.Так что те же правила применяются к Foo
.
Если это так (и, пожалуйста, исправьте меня, если у меня есть грубое заблуждение здесь), почему бы не объявить элемент данных открытым и упростить вещи?
Поскольку:
- вы можете хранить изменяемые данные внутри объекта и предоставлять только неизменяемые (только для чтения) представления данных (например, переносколлекции)
- вы можете изменить реализацию в будущем, избавиться от поля и, например, вычислить значение на лету.