64 votes

clone ou copie de java.util.Date pour ne pas exposer la référence interne

La meilleure pratique consiste à ne pas exposer les références internes d'un objet (entité). Ainsi, si un Object possède un champ de type java.util.Date alors par exemple le getter pour ce champ ne devrait pas retourner la date originale mais une copie de celle-ci.

Mais pour une date java.util.Date, il existe deux façons courantes de créer cette copie :

  • clone : (Date) originalDate.clone()
  • copie via le constructeur new Date(originalDate.getTime())

Ma question est la suivante : quelle est la meilleure solution, et pourquoi ?

43voto

Jon Skeet Points 692016

Si c'est vraiment juste un Date cela ne fera aucune différence dans les deux cas.

Si l'objet réel peut être un sous-classe de Date (par exemple java.sql.Date ) alors j'espère que clone() conserverait les informations supplémentaires (y compris la classe dont il s'agit) alors que l'appel au constructeur ne le ferait pas.

En passant, si vous avez utilisé Joda Time vous n'auriez pas ce problème, car il existe de nombreux types immuables à utiliser. C'est aussi une bien meilleure API :)

35voto

Amir Afghani Points 17519

Lire Java efficace . La meilleure façon de créer des copies est d'utiliser l'approche du constructeur de copie.

Bill Venners : Dans votre livre, vous recommandez d'utiliser un constructeur de copie au lieu d'implémenter Cloneable et d'écrire clone. Pouvez-vous élaborer sur ce point ?

Josh Bloch : Si vous avez lu l'article sur le clonage dans mon livre, surtout si vous lisez entre les lignes, vous saurez que je pense que clone est profondément cassé. Il y a quelques défauts de conception, le plus important étant que le plus important est que l'interface Cloneable n'a pas de méthode de clonage. Et cela signifie que cela ne fonctionne tout simplement pas : rendre quelque chose Cloneable ne dit rien sur ce que vous pouvez en faire. Au lieu de cela, cela indique quelque chose sur ce qu'il peut faire en interne. Il est dit que si en appelant super.clone de manière répétée, il finit par appeler la méthode clone d'Object, cette méthode renverra une copie du champ de l'objet. méthode retournera une copie du champ de l'original.

16voto

robpvn Points 312

Si vous codez de manière défensive, vous voudrez le constructeur de copie. Voir ce passage de Effective Java :

Notez également que nous n'avons pas utilisé la méthode clone de Date pour effectuer les copies défensives. Étant donné que Date n'est pas finale, la méthode clone n'est pas garantie de renvoyer un objet dont la classe est java.util.Date ; elle pourrait renvoyer une instance d'une sous-classe non fiable spécialement conçue pour les méfaits. Une telle sous-classe pourrait, par exemple, enregistrer une référence à chaque instance dans une liste statique privée au moment de sa création et permettre à l'attaquant d'accéder à cette liste. L'attaquant aurait ainsi le champ libre sur toutes les instances. Pour éviter ce type d'attaque, n'utilisez pas la méthode clone pour faire une copie défensive d'un paramètre dont le type peut être sous-classé par des parties non fiables.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X