-
Notifications
You must be signed in to change notification settings - Fork 3
How about Clone?
Иногда мы работаем с неизменяемыми объектами, тогда, при работе с таким объектом часто бывает полезно создать его копию и работать с ней. Также часто бывает создать копию какого-либо объекта и работать с ней, при этом не изменяя первоначальный объект.
Одним из способов клонировать объект является переопределение метода clone() и реализация интерфейса Cloneable();
.
У объекта Object
есть метод clone
, как он объявлен?
protected Object clone() throws CloneNotSupportedException
По умолчанию этот метод определяет 'поверхностное' копирование, копируются значения всех полей и ссылок. Так как он protected
, то у объектов, не переопределивших его, этот метод не получится вызвать.
Заметим также, что с версии 1.5 хорошим тоном при переопределении этого метода является явное указание возвращаемого объекта, а не Object.
В java есть интерфейс-маркер Cloneable
, который показывает, может ли объект быть клонирован. Классы, открывающие метод clone
обязаны реализовывать этот интерфейс.
Сам Object
- это не реализует этот интерфейс.
Почему? Потому, что не всем классам это надо. Не все классы обязательно должны уметь клонироваться. А реализовав интерфейс в Object
мы бы потащили его везде.
Однако, как мы помним, если поля класса содержат ссылки на изменяемые объекты, то при клонировании будет скопирована именно ссылка, а значит, изменив такое поле в клоне объекта - мы измени его и в оригинальном!
А это может иметь печальные последствия.
Избежать можно вот как: воспользоваться конструктором копирования.
Т.е сначала вызвать clone
супер класса, а после уже работать с такими опасными полями.
Отметим, что клонирование таким способом НЕ работает, если поле помечено как final
.
Все методы, реализующие Cloneable должны переопределять clone и делать его открытым. В переопределенном методе необходимо сначала вызвать super.clone()
, после чего начать работать с полями, значения которых могут изменяться, т.е надо заменять все ссылки на объекты соответствующими копиями.
Лучшим вариантом является определение конструктора-копий или статический метод генерации.
Плюсы таких вариантов заключается в том, что это проще, клиент получает объект определенного типа, не отлавливает исключения, можно работать с final
полями.
Этот вариант является гораздо более предпочтительным.