2011-08-16 13 views
60

Es una buena práctica no exponer las referencias internas de un objeto (entidad). Entonces, si un Objeto tiene un campo de tipo java.util.Date entonces, por ejemplo, el getter para este campo no debe devolver la fecha original sino una copia de este.java.util.Date clone o copie para no exponer la referencia interna

Pero para un java.util.Date hay dos formas comunes para crear esa copia:

  • clon: (Date) originalDate.clone()
  • copia por el constructor new Date(originalDate.getTime())

Mi pregunta es, que camino es mejor, y por qué?

Respuesta

40

Si es definitivamente solo Date, no hará ninguna diferencia de ninguna manera.

Si el objeto real podría ser una subclase de Date (como java.sql.Date) entonces yo espero que clone() sería conservar la información adicional (incluyendo qué clase es), mientras que una llamada al constructor no lo haría.

Como un lado, si usaste Joda Time no tendrías este problema, ya que hay muchos tipos inmutables para usar. También es una API mucho mejor :)

+6

A partir de Java 8 java.time API se puede utilizar en lugar de Joda Time. – Akash

33

Lea Effective Java. La forma preferida de crear copias es usar el enfoque del constructor de copias.

Bill Venners: en su libro, recomendamos utilizar un constructor de copia en lugar de implementar Cloneable y escribir clonar. ¿Podría profundizar en eso?

Josh Bloch: Si ha leído el artículo acerca de la clonación en mi libro, especialmente si lee entre líneas, sabrá que creo que el clon está muy roto. Hay algunos defectos de diseño, el más grande de que es que la interfaz Cloneable no tiene un método de clonación. Y eso significa que simplemente no funciona: hacer algo clonable no dice nada sobre lo que puede hacer con él. En cambio, dice algo sobre lo que puede hacer internamente. Dice que si llamando repetidamente al super.clone termina llamando al método de clonación de Object, este método devolverá una copia de campo del original.

+5

Esa es la forma preferida de diseñar la clonación en sus propias clases, aunque requiere que la persona que llama * sepa * qué subclase concreta se usa o no * cuidado * qué subclase concreta se utiliza. Vea mi respuesta para ver un ejemplo de cómo puede marcar la diferencia. –

14

Si está codificando a la defensiva, querrá el constructor de copias. Consulte this passage from Effective Java:

Tenga en cuenta también que no utilizamos el método de clonación de Date para realizar las copias defensivas. Como Date no es final, no se garantiza que el método clon devuelva un objeto cuya clase sea java.util.Date; podría devolver una instancia de una subclase no confiable específicamente diseñada para daños maliciosos. Dicha subclase podría, por ejemplo, registrar una referencia a cada instancia en una lista privada estática en el momento de su creación y permitir al atacante acceder a esta lista. Esto le daría al atacante dominio libre sobre todas las instancias. Para evitar este tipo de ataque, no use el método de clonación para hacer una copia defensiva de un parámetro cuyo tipo sea subclassable por partes no confiables.

Cuestiones relacionadas