java.util.Date клонировать или копировать, чтобы не показывать внутреннюю ссылку - PullRequest
63 голосов
/ 16 августа 2011

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

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

  • клон: (Date) originalDate.clone()
  • копия с помощью конструктора new Date(originalDate.getTime())

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

Ответы [ 3 ]

43 голосов
/ 16 августа 2011

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

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

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

35 голосов
/ 16 августа 2011

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

Билл Веннерс: в своей книге вы рекомендуете использовать конструктор копирования вместо реализации Cloneable и написания клона. Можешь ли ты уточни это?

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

15 голосов
/ 05 февраля 2013

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

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

...