dans le livre Java Concurrence dans la pratique explique les avantages des objets "efficacement immuables" par rapport aux objets mutables de la concurrence . Mais cela n'explique pas quel avantage les objets "efficacement immutables" offriraient des objets immuables vraiment em>. P>
Et je ne comprends pas: tu ne peux pas toujours em> construire un objet vraiment immuable pour le moment que vous décideriez de publier en toute sécurité un objet "efficacement immuable"? (au lieu de faire votre "publication sûre", vous construirez un objet vraiment immuable et c'est tout) em> p>
Lorsque je concevons des cours, je ne vois pas les cas où je ne pouvais pas toujours construire un objet vraiment immuable (à l'aide de la délégation si nécessaire, etc. Pour construire d'autres objets emballés, elles-mêmes vraiment immoussables bien sûr) au moment où je voudrais décider de "publier en toute sécurité". P>
Ainsi sont un objet "efficacement immuable" et leur "publication sûre", juste un cas de mauvais design ou de mauvaises API? P>
Où seriez-vous obligé d'utiliser un objet efficacement immuable et d'être obligé de le publier en toute sécurité où vous ne pouviez pas construire un objet très élevé vraiment immuable? P>
4 Réponses :
Oui, ils ont du sens dans certains cas. Un exemple facile est que lorsque vous voulez que certaines propriétés soient générées paresseusement et mises en cache afin que vous puissiez éviter les frais généraux de la générer s'il n'est jamais accessible. String CODE> est un exemple de classe efficacement immuable qui le fait (avec son hachemode). P>
Utiliser efficacement des objets immuables vous permet d'éviter de créer un nombre considérable de classes. Au lieu de faire des paires de classes [de constructeur mutable] / [objet immuable], vous pouvez construire une classe efficacement immuable. Je définis généralement une interface immuable et une classe mutable implémente cette interface. Un objet est configuré via ses méthodes de classe mutable, puis publiées via son interface immuable. Tant que les clients de votre programme de bibliothèque à l'interface, vos objets restent immuables à travers leur durée de vie publiée. P>
Un exemple de cette approche disponible?
pour les immutables circulaires: une question est, car retour à votre question initiale. En pratique, il y a toujours des contraintes au-delà des purs techniques. Initialiser tout à l'intérieur du constructeur n'est pas nécessairement la meilleure option pour une conception, compte tenu de toutes les raisons d'ingénierie, opérationnelles, politiques et autres humaines. P> se demandant pourquoi nous sommes nourris de penser que c'est une bonne idée suprême ? P> Le problème plus profond est Java manque em> un fichier général bon marché pour une publication sûre qui est moins chère que volatile. Java n'a que pour maintenant groupage de deux significations sous un ceci code> de
FOOA code> est divulgué à l'intérieur du constructeur, est
FOOA code> toujours un fil de sécurité immuable? C'est-à-dire que si un autre thread lit
foob.gether (). Param code>, est-il garanti de voir
parama code>? La réponse est oui, car
ceci code> n'est pas divulgué à un autre fil avant le geler em> action; Nous pouvons établir des commandes HB / CC / MC requises par SPECT pour prouver que
parama code> est la seule valeur visible de la lecture. P>
Final code> champs; Pour une raison quelconque, cette clôture n'est pas disponible sinon. p>
final code> porte deux significations indépendantes: 1er, qu'un champ final doit être attribué exactement une fois; 2ème, la sémantique de la mémoire de la publication sûre. Ces deux significations n'ont rien à voir avec l'autre. Il est assez déroutant de les regrouper. Lorsque les gens ont besoin de la 2e signification, ils sont obligés d'accepter le 1er signification aussi. Lorsque le 1er est très gênant de réaliser dans une conception, les gens se demandent ce qu'ils ont mal fait - ne réalisant pas que c'est Java qui s'est trompé. P>
final code> Le rend double plus bon, de sorte que nous avons apparemment plus de raison et de motivation à utiliser
final code>. L'histoire plus sinistre est en fait, nous sommes obligés de l'utiliser car nous n'avons pas donné de choix plus flexible. P> p>
+1 pour le grand exemple et l'explication. Aussi, je n'ai pas mentionné "final" mais c'est bien ce que nous devons utiliser ... En ce qui concerne les deux significations: il est encore plus déroutant vu que finale i> peut également être appliqué à des méthodes, mais je me digresse; ) J'aime l'exemple du constructeur bien que l'on puisse également le faire à l'aide d'une usine et / ou d'une interface fluide.
Supposons que l'on a une classe immuable ick. Une violation massive de «Ne vous répétez pas» (sèche)). En outre, l'ajout d'une nouvelle propriété à la classe nécessiterait de l'ajouter à chacune de ces méthodes. P> d'autre part, si chaque Le nombre de lignes de code de code pour chaque méthode a augmenté, mais les méthodes ne nécessitent plus besoin de Pour faire référence à toutes les propriétés, ils ne sont pas "intéressés". Notez que lorsqu'un FOO code> avec cinq propriétés, nommée
alpha code>,
bêta code>, etc., et on souhaite fournir
Withalpha code>,
withbeta code>, etc. Méthodes qui retourneront une instance identique à l'original, sauf avec la propriété particulière modifiée. Si la classe est vraiment et profondément immuable, les méthodes doivent prendre la forme:
foo code> a tenu un
fooguts interne code> qui comprenait un constructeur de copie, on pourrait plutôt faire quelque chose comme: p>
FOO code> pourrait ne pas être immuable si son constructeur a été appelé avec un
fooguts code> sur lequel Il existait de la référence extérieure, son constructeur n'est accessible qu'au code qui est de confiance à ne pas maintenir une telle référence après la construction. P> P>