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

Il est recommandé de ne pas exposer les références internes d’un object (entité). Donc, si un object a un champ de type java.util.Date alors, par exemple, le getter pour ce champ ne doit pas renvoyer la date d’origine mais une copie.

Mais pour un fichier java.util.Date, il existe deux méthodes courantes pour créer cette copie:

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

Ma question est la suivante: quelle voie est la meilleure et pourquoi?

Si ce n’est définitivement qu’une Date , cela ne fera aucune différence.

Si l’object réel peut être une sousclasse de Date (comme java.sql.Date ), j’espère que clone() conservera les informations supplémentaires (y compris la classe) alors que l’appel du constructeur ne le ferait pas.

En passant, si vous utilisiez Joda Time, vous n’auriez pas ce problème, car il y a beaucoup de types immuables à utiliser. C’est aussi une API bien meilleure 🙂

Lire Java efficace . La méthode préférée pour créer des copies consiste à 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 des clones. Pouvez-vous développer sur ce sujet?

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 le clone est profondément brisé. Il y a quelques défauts de conception, le plus important étant que l’interface clonable ne possède pas de méthode de clonage. Cela signifie que cela ne fonctionne tout simplement pas: faire quelque chose Clonable ne dit rien de ce que vous pouvez en faire. Au lieu de cela, il dit quelque chose sur ce qu’il peut faire en interne. Il dit que si en appelant plusieurs fois super.clone, il finit par appeler la méthode de clonage d’Object, cette méthode renverra une copie de champ de l’original.

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

Notez également que nous n’avons pas utilisé la méthode de clonage de Date pour créer les copies défensives. Dans la mesure où Date n’est pas définitive, la méthode clone n’est pas garantie de renvoyer un object dont la classe est java.util.Date; il pourrait renvoyer une instance d’une sous-classe non fiable spécialement conçue pour les méfaits malveillants. 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. Cela donnerait à l’attaquant un règne libre sur toutes les instances. Pour éviter ce type d’attaque, n’utilisez pas la méthode clone pour créer une copie défensive d’un paramètre dont le type est sous-classable par des parties non fiables.