Хорошие ответы уже придумали, но позвольте мне придумать другие примеры и ссылки
Лучший источник для объяснения будет Effective Java Джош Блох. Есть как минимум две главы о неизменяемости и защитных копиях.
Чтобы сделать это коротко: В Java вы передаете все по ссылке (я знаю, что это упрощенно, но это не так), и многие классы изменяемы. Следовательно, прямое назначение частного поля с внешним объектом не является действительно безопасным, поскольку значение под ним может меняться в любой момент времени за пределами объекта, нарушая инкапсуляцию.
Методы доступа - суть разрушения инкапсуляции. В наиболее распространенной реализации вы просто публикуете поле и, как упоминалось выше, вы разрешаете кому-либо изменять базовые объекты, если они позволяют это делать. Лучший пример - коллекции ИМХО. Если вы вернете любую сборку Java по умолчанию, любой может добавить что-то к ней, удалить элемент или даже очистить его. Если ваша логика зависит от состояния или вы пишете многопоточное приложение, это самый простой способ получить состояние гонки, чего мы действительно не хотим.
Так хорошая практика либо
- возвращая глубокую копию объекта (например, методы гуавы сбора копии)
- возвращающего взгляд на объекте (например, класс Collections и его метода)
- используя неизменные объекты (самый простой из их всех)
- клонирования или другого фанки бизнеса
Каждый из этих часов а некоторые из них связаны с ними. Копирование/клонирование требует времени и памяти. Представления не полностью безопасны, поскольку базовая реализация может измениться в любой момент времени, неизменные объекты не позволяют изменять и их трудно реализовать в унаследованных системах и т. Д. Вам решать найти баланс, но мы всегда рады помочь:)
Последнее, что также является хорошей практикой делать защитную копию в конструкторе/сеттер переданного в изменяемом параметре по той же причине. Если кто-то добавит элементы в коллекцию, которые мы сделали final в конструкторе, это было бы довольно глупо, c, мы не сохраняем состояние, которое мы, очевидно, хотели.Таким образом, в конструкторе не выполняется простая инициализация, если вы не контролируете, что было передано (и даже если вы это сделаете, это может быть хорошей идеей для копирования)
Я предпочитаю коллекции в качестве примера , поскольку они легче рассуждать о том, как сделать копию/как они меняются, однако StringBuilder и Date, упомянутые в других ответах, действительно показывают, что это не только выпуск коллекций. Итак, лучший ответ: Помните, финал - ваш лучший друг. Используйте это часто, с самого начала, и никогда не доверяйте изменчивым незнакомцам!
Аспект сбора мусора является спорным. Я думаю: он может быстрее очистить эту конкретную ссылку, но это также приводит к тому, что GC происходит чаще. Основная цель, вероятно, неизменна. –