Java.util.Date клонировать или копировать, чтобы не выставлять внутреннюю ссылку

Лучше всего не открывать внутренние ссылки объекта (объекта). Поэтому, если у объекта есть поле типа java.util.Date, то, например, getter для этого поля должен возвращать не исходную дату, а копию ее.

Но для java.util.Date существуют два общих способа создания этой копии:

  • clone: ​​(Date) originalDate.clone()
  • копировать через конструктор new Date(originalDate.getTime())

Мой вопрос в том, какой путь лучше, и почему?

Ответ 1

Если это определенно просто Date, это не будет иметь никакого значения в любом случае.

Если фактический объект может быть подклассом Date (например, java.sql.Date), я надеюсь, что clone() сохранит дополнительную информацию (включая класс), тогда как вызов конструктора не будет.

В стороне, если вы использовали Joda Time, у вас не было бы этой проблемы, так как есть много неизменяемых типов для использования. Это также намного лучший API:)

Ответ 2

Прочитайте Эффективное Java. Предпочтительным способом создания копий является использование подхода конструктора копирования.

Bill Venners: в ​​своей книге вы рекомендуете использовать конструктор копирования вместо того, чтобы внедрять клонированный и записывающий клон. Могли бы вы уточните это?

Джош Блох: Если вы прочитали статью о клонировании в моей книге, особенно если вы читаете между строками, вы будете знать, что я думаю клон глубоко сломан. Есть несколько недостатков дизайна, самый большой из что интерфейс Cloneable не имеет метода клонирования. И это означает, что он просто не работает: что-то делает Cloneable ничего не говорит о том, что вы можете с этим сделать. Вместо этого говорится: что-то о том, что он может делать внутренне. В нем говорится, что если super.clone неоднократно завершает вызов метода клонирования Object, это метод вернет копию экземпляра оригинала.

Ответ 3

Если вы кодируете оборонительно, вам понадобится конструктор копирования. См. этот отрывок из Эффективной Java:

Обратите внимание также, что мы не использовали метод клонирования Date для создания защитных копий. Поскольку Date является нефинальным, метод clone не гарантированно возвращает объект, чей класс java.util.Date; он может вернуть экземпляр ненадежного подкласса, специально разработанного для вредоносного вреда. Такой подкласс может, например, записывать ссылку на каждый экземпляр в приватном статическом списке во время его создания и разрешать злоумышленнику доступ к этому списку. Это давало бы злоумышленнику свободное владение над всеми экземплярами. Чтобы предотвратить подобную атаку, не используйте метод clone для создания защитной копии параметра, тип которого является подклассом недоверенными сторонами.