web-dev-qa-db-fra.com

Pourquoi les chaînes sont-elles immuables dans de nombreux langages de programmation?

Duplicata possible:
Pourquoi les chaînes ne peuvent-elles pas être mutables dans Java et .NET?
Pourquoi la chaîne .NET est immuable?

Plusieurs langages ont choisi pour cela, comme C #, Java et Python. S'il vise à économiser de la mémoire ou à gagner en efficacité pour des opérations comme comparer, quel effet cela a-t-il sur la concaténation et les autres opérations de modification?

60
snowfox

Les types immuables sont généralement une bonne chose:

  • Ils fonctionnent mieux pour la concurrence (vous n'avez pas besoin de verrouiller quelque chose qui ne peut pas changer!)
  • Ils réduisent les erreurs: les objets mutables sont susceptibles d'être modifiés lorsque vous ne vous y attendez pas, ce qui peut introduire toutes sortes de bugs étranges ("action à distance")
  • Ils peuvent être partagés en toute sécurité (c'est-à-dire plusieurs références au même objet), ce qui peut réduire la consommation de mémoire et améliorer l'utilisation du cache.
  • Le partage permet également de copier une opération O(1) très bon marché quand elle serait O(n) si vous devez prendre une copie défensive d'un objet mutable). C'est un gros problème car la copie est une opération incroyablement courante (par exemple chaque fois que vous voulez passer des paramètres ...)

En conséquence, c'est un choix de conception de langage assez raisonnable pour rendre les chaînes immuables.

Certains langages (en particulier les langages fonctionnels comme Haskell et Clojure) vont encore plus loin et rendent à peu près tout immuable. Cette vidéo éclairante vaut vraiment le détour si vous êtes intéressé par les avantages de l'immuabilité.

Il existe quelques inconvénients mineurs pour les types immuables:

  • Les opérations qui créent une chaîne modifiée comme la concaténation sont plus coûteuses car vous devez construire de nouveaux objets. En règle générale, le coût est O (n + m) pour la concaténation de deux chaînes immuables, bien qu'il puisse aller aussi bas que O (log (m + n)) si vous utilisez une structure de données de chaîne arborescente comme une corde . De plus, vous pouvez toujours utiliser des outils spéciaux tels que Java StringBuilder si vous avez vraiment besoin de concaténer efficacement des chaînes.
  • Un petit changement sur une grande chaîne peut entraîner la nécessité de construire une copie entièrement nouvelle de la grande chaîne, ce qui augmente évidemment la consommation de mémoire. Notez cependant que ce n'est généralement pas un gros problème dans les langues récupérées car la vieille copie sera récupérée assez rapidement si vous ne conservez pas de référence.

Dans l'ensemble cependant, les avantages de l'immuabilité l'emportent largement sur les inconvénients mineurs. Même si vous n'êtes intéressé que par les performances, les avantages de la concurrence et le coût peu élevé de la copie rendront généralement les chaînes immuables beaucoup plus performantes que les chaînes mutables avec verrouillage et copie défensive.

73
mikera

Il est principalement destiné à éviter les erreurs de programmation. Par exemple, les chaînes sont fréquemment utilisées comme clés dans les tables de hachage. S'ils pouvaient changer, la table de hachage serait corrompue. Et ce n'est qu'un exemple où la modification d'un élément de données pendant que vous l'utilisez pose des problèmes. La sécurité en est une autre: si vous vérifiez si un utilisateur est autorisé à accéder à un fichier à un chemin donné avant d'exécuter l'opération qu'il a demandée, la chaîne contenant le chemin ne doit pas être mutable ...

Cela devient encore plus important lorsque vous faites du multithreading. Les données immuables peuvent être transmises en toute sécurité entre les threads tandis que les données mutables provoquent des maux de tête sans fin.

Fondamentalement, les données immuables facilitent la réflexion sur le code qui y fonctionne. C'est pourquoi les langages purement fonctionnels essaient de garder tout immuable.

16

In Java non seulement String mais toutes les classes Wrapper primitives (Integer, Double, Character etc.) sont immuables. Je ne suis pas sûr de la raison exacte mais je pense que ce sont les types de données de base sur lesquels tous les schémas de programmation fonctionnent. S'ils changent, les choses pourraient se déchaîner. Pour être plus précis, je vais utiliser un exemple: disons que vous avez ouvert une connexion socket à un hôte distant. Le nom d'hôte serait une chaîne et le port serait un entier Que faire si ces valeurs sont modifiées une fois la connexion établie.

En ce qui concerne les performances, Java alloue de la mémoire à ces classes à partir d'une section de mémoire distincte appelée Literal Pool, et non à partir de la pile ou du tas. Le Literal Pool est indexé et si vous utilisez une chaîne " Chaîne "deux fois, ils pointent vers le même objet du pool littéral.

3
Ameya

Le fait d'avoir des chaînes aussi immuables permet également de faciliter les nouvelles références de chaînes, car les mêmes chaînes/similaires seront facilement disponibles à partir du pool des chaînes précédemment créées. Réduisant ainsi le coût de la création de nouveaux objets.

0
saurabytes