206 votes

Pourquoi les chaînes de caractères ne peuvent-elles pas être mutables en Java et .NET ?

Comment se fait-il qu'ils aient décidé de faire String immuable en Java et .NET (et dans certains autres langages) ? Pourquoi ne l'ont-ils pas rendu mutable ?

13 votes

J'ai eu la même pensée, mais j'ai vérifié l'emplacement des posters originaux et j'ai trouvé qu'ils sont de Belgique. Cela signifie qu'il est peu probable qu'il soit de langue maternelle anglaise. Si l'on ajoute à cela le fait que la plupart des natifs ont une connaissance approximative de la langue, j'ai décidé de la laisser tranquille.

8 votes

Merci belugabob, mais je ne suis pas une elle, je suis un lui. Apparemment, les gens ne tiennent pas compte des différences culturelles.

7 votes

Mes excuses - chrissie est (généralement) un nom de fille au Royaume-Uni - ce qui fait de moi une victime d'une autre différence culturelle :-)

218voto

PRINCESS FLUFF Points 2072

Selon Java efficace chapitre 4, page 73, 2e édition :

" Il y a de nombreuses bonnes raisons à cela : Les classes immuables sont plus faciles à conception, d'implémentation et d'utilisation que les classes mutables. Elles sont moins sujettes aux erreurs et sont plus sûres.

[...]

" Les objets immuables sont simples. Un objet immuable peut être dans un seul état, celui dans lequel il a été créé. Si vous vous assurez que tous les constructeurs établissent des invariants de classe, alors il est garantie que ces invariants resteront vrais à tout moment, sans aucun aucun effort de votre part.

[...]

Les objets immuables sont intrinsèquement sûrs pour les fils de discussion ; ils ne nécessitent aucune synchronisation. Ils ne peuvent pas être corrompus par de multiples fils. qui y accèdent simultanément. C'est de loin l'approche la plus simple pour assurer la sécurité des threads. En fait, aucun thread ne peut jamais observer effet d'un autre thread sur un objet immuable. Par conséquent, les objets immuables peuvent être partagés librement

[...]

Autres petits points du même chapitre :

Non seulement vous pouvez partager des objets immuables, mais vous pouvez également partager leurs éléments internes.

[...]

Les objets immuables constituent d'excellents blocs de construction pour d'autres objets, qu'ils soient mutables ou immuables.

[...]

Le seul véritable inconvénient des classes immuables est qu'elles nécessitent un objet séparé pour chaque valeur distincte.

23 votes

Lisez la deuxième phrase de ma réponse : Les classes immuables sont plus faciles à concevoir, à mettre en œuvre et à utiliser que les classes mutables. Elles sont moins sujettes aux erreurs et sont plus sûres.

6 votes

@PRINCESSFLUFF J'ajouterais que le partage de chaînes mutables est dangereux même sur un seul thread. Par exemple, en copiant un rapport : report2.Text = report1.Text; . Puis, ailleurs, en modifiant le texte : report2.Text.Replace(someWord, someOtherWord); . Cela modifierait le premier rapport ainsi que le second.

12 votes

@Sam il n'a pas demandé "pourquoi ils ne peuvent pas être mutables", il a demandé "pourquoi ils ont décidé de les rendre immuables" ce à quoi ceci répond parfaitement.

104voto

smink Points 39640

Il y a au moins deux raisons.

Premièrement - la sécurité http://www.javafaq.nu/java-article1060.html

La principale raison pour laquelle String a fait immuable était la sécurité. Regardez cet exemple : Nous avons une méthode d'ouverture de fichier avec vérification de la connexion. Nous passons une chaîne à cette méthode pour traiter l'authentification qui est nécessaire avant que l'appel soit transmis au système d'exploitation. Si la chaîne est mutable, il était possible d'une manière ou d'une autre de modifier son contenu après la contrôle d'authentification avant que l'OS ne reçoive demande du programme, alors il est possible possible de demander n'importe quel fichier. Ainsi, si vous avez le droit d'ouvrir un fichier texte dans répertoire de l'utilisateur mais qu'à la volée si vous parvenez à changer le nom du fichier nom du fichier, vous pouvez demander à ouvrir le fichier "passwd" ou un autre. Ensuite, un fichier fichier peut être modifié et il sera possible de se connecter directement à l'OS.

Deuxièmement - Efficacité de la mémoire http://hikrish.blogspot.com/2006/07/why-string-class-is-immutable.html

La JVM gère en interne le "String Pool". Pour atteindre l'efficacité de la mémoire l'efficacité de la mémoire, la JVM référera l'objet String à partir du pool. Elle ne créera pas les nouveaux objets String. Ainsi, chaque fois que vous créez une nouvelle chaîne littérale, la JVM vérifiera dans le pool si elle existe déjà ou non. Si elle est déjà présent dans le pool, il suffit de donner la référence au même objet ou de créer le nouvel objet dans le pool. Il y aura de nombreuses références pointent vers les mêmes objets String, si quelqu'un change la valeur, cela affectera toutes les références. Donc, Sun a décidé de la rendre immuable.

0 votes

C'est un bon point concernant la réutilisation, et particulièrement vrai si vous utilisez String.intern(). Il aurait été possible de réutiliser sans rendre toutes les chaînes immuables, mais la vie a tendance à se compliquer à ce stade.

3 votes

Aucune de ces raisons ne me semble terriblement valable à notre époque.

0 votes

Je ne suis pas ému par la raison de sécurité. Le processus d'authentification peut copier la valeur de la chaîne dans un nouvel objet interne avant la vérification.

59voto

LordOfThePigs Points 3853

En fait, les raisons pour lesquelles les chaînes sont immuables en Java n'ont pas grand-chose à voir avec la sécurité. Les deux principales raisons sont les suivantes :

Sécurité de la théade :

Les chaînes de caractères sont un type d'objet extrêmement répandu. Il est donc plus ou moins garanti qu'elles seront utilisées dans un environnement multithread. Les chaînes de caractères sont immuables afin de garantir la sécurité du partage des chaînes de caractères entre les threads. Le fait d'avoir des chaînes immuables garantit que, lors du passage de chaînes du thread A à un autre thread B, le thread B ne peut pas modifier inopinément la chaîne du thread A.

Cela permet non seulement de simplifier la tâche déjà assez compliquée de la programmation multithread, mais aussi d'améliorer les performances des applications multithread. L'accès aux objets mutables doit être synchronisé d'une manière ou d'une autre lorsqu'ils sont accessibles à partir de plusieurs threads, afin de s'assurer qu'un thread ne tente pas de lire la valeur de votre objet pendant qu'il est modifié par un autre thread. Une synchronisation appropriée est à la fois difficile à réaliser correctement pour le programmeur et coûteuse au moment de l'exécution. Les objets immuables ne peuvent pas être modifiés et n'ont donc pas besoin de synchronisation.

Performance :

Bien que l'internage des chaînes de caractères ait été mentionné, il ne représente qu'un faible gain d'efficacité mémoire pour les programmes Java. Seuls les littéraux de chaîne sont internés. Cela signifie que seules les chaînes de caractères qui sont les mêmes dans votre fichier code source partageront le même String Object. Si votre programme crée dynamiquement des chaînes qui sont identiques, elles seront représentées dans des objets différents.

Plus important encore, les chaînes immuables leur permettent de partager leurs données internes. Pour de nombreuses opérations sur les chaînes, cela signifie que le tableau de caractères sous-jacent ne doit pas être copié. Par exemple, disons que vous voulez prendre les cinq premiers caractères de String. En Java, vous appelleriez maChaîne.substring(0,5). Dans ce cas, la méthode substring() crée simplement un nouvel objet String qui partage le char[] sous-jacent de myString mais qui sait qu'il commence à l'indice 0 et se termine à l'indice 5 de ce char[]. Pour exprimer cela sous forme graphique, vous obtiendrez ce qui suit :

 |               myString                  |
 v                                         v
"The quick brown fox jumps over the lazy dog"   <-- shared char[]
 ^   ^
 |   |  myString.substring(0,5)

Cela rend ce type d'opérations extrêmement bon marché, et O(1) puisque l'opération ne dépend ni de la longueur de la chaîne originale, ni de la longueur de la sous-chaîne que nous devons extraire. Ce comportement présente également des avantages en termes de mémoire, puisque de nombreuses chaînes de caractères peuvent partager leur char[] sous-jacent.

6 votes

L'implémentation des sous-chaînes en tant que références qui partagent le sous-jacent char[] est une décision de conception plutôt discutable. Si vous lisez un fichier entier dans une seule chaîne et que vous maintenez une référence à une seule sous-chaîne d'un caractère, le fichier entier devra être conservé en mémoire.

5 votes

Exactement, j'ai rencontré ce problème particulier lors de la création d'un robot d'exploration de site Web qui ne devait extraire que quelques mots de la page entière. Le code HTML de la page entière était en mémoire, et à cause de substring partageant le char[], j'ai gardé le code HTML entier même si je n'avais besoin que de quelques octets. Une solution à ce problème est d'utiliser new String(original.substring(..,..)), le constructeur String(String) fait une copie de la plage concernée du tableau sous-jacent.

1 votes

Un addendum pour couvrir les changements ultérieurs : Depuis Jave 7, String.substring() effectue une copie complète, afin d'éviter les problèmes mentionnés dans les commentaires ci-dessus. En Java 8, les deux champs permettant char[] le partage, à savoir count y offset sont supprimés, ce qui réduit l'empreinte mémoire des instances String.

32voto

Matt Howells Points 20751

Sécurité et performance des filets. Si une chaîne ne peut pas être modifiée, il est sûr et rapide de faire circuler une référence entre plusieurs threads. Si les chaînes étaient mutables, il faudrait toujours copier tous les octets de la chaîne dans une nouvelle instance, ou fournir une synchronisation. Une application typique lira une chaîne 100 fois à chaque fois que cette chaîne devra être modifiée. Voir wikipedia sur immutabilité .

11voto

Esko Luontola Points 53877

On devrait vraiment se demander, "pourquoi X devrait-il être mutable ?" Il vaut mieux opter pour l'immuabilité par défaut, en raison des avantages déjà mentionnés par Princesse Fluff . Le fait que quelque chose soit mutable devrait être une exception.

Malheureusement, la plupart des langages de programmation actuels optent par défaut pour la mutabilité, mais nous espérons qu'à l'avenir, le choix se portera davantage sur l'immuabilité (cf. Une liste de souhaits pour le prochain langage de programmation grand public ).

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