On m'a demandé dans une interview pourquoi String est immuable
J'ai répondu comme ça:
Lorsque nous créons une chaîne en Java comme
String s1="hello";
, alors un objet sera créé dans chaîne pool (hello) et s1 sera pointant vers bonjour . Maintenant si on refaitString s2="hello";
puis un autre objet ne sera pas créé mais s2 désignerahello
Parce queJVMvérifiera d’abord si le même objet est présent dans string pool ou not.Si non présent, seul un nouveau est créé, sinon.
Maintenant, si supposons que Java autorise la chaîne mutable, si nous changeons s1 en hello world
, alors s2 value sera également hello world
, de sorte que Java String est immuable.
Est-ce que n'importe qui peut me dire si ma réponse est bien ou mal ?
String
est immuable pour plusieurs raisons, voici un résumé:
String
dans les connexions réseau, les URL de connexion à la base de données, les noms d'utilisateur/mots de passe, etc. S'il était modifiable, ces paramètres pourraient être facilement modifiés.String
est utilisé comme argument pour le chargement de classe. Si mutable, cela pourrait entraîner le chargement d'une mauvaise classe (car les objets mutables changent d'état).Cela étant dit, l’immuabilité de String
signifie seulement que vous ne pouvez pas le changer en utilisant son API publique. Vous pouvez en fait contourner l’API normale en utilisant la réflexion. Voir la réponse ici.
Dans votre exemple, si String
était modifiable, considérons l'exemple suivant:
String a="stack";
System.out.println(a);//prints stack
a.setValue("overflow");
System.out.println(a);//if mutable it would print overflow
Les développeurs Java décident que les chaînes sont immuables en raison de l'aspect suivant conception, efficacité et sécurité.
Design Les chaînes sont créées dans une zone mémoire spéciale du segment de mémoire Java appelée "Pool Intern String". Lorsque vous créez un nouveau String (sauf si vous utilisez le constructeur String () ou toute autre fonction String qui utilise en interne le constructeur String () pour créer un nouvel objet String, le constructeur String () crée toujours une constante chaîne dans le pool, sauf si Appelez la variable method intern () ) pour rechercher dans le pool s'il existe déjà. S'il existe, retournez la référence de l'objet String existant. Si la chaîne n'est pas immuable. , modifier la chaîne avec une référence entraînera une valeur incorrecte pour les autres références.
Selon this article sur DZone:
Sécurité La chaîne est largement utilisée en tant que paramètre pour de nombreuses classes Java, par exemple. connexion réseau, ouverture de fichiers, etc. Si String n'était pas immuable, une connexion ou un fichier serait modifié et entraînerait une menace grave pour la sécurité . Les chaînes mutables peuvent également poser un problème de sécurité dans Reflection, car les paramètres sont des chaînes.
Efficacité Le hashcode de string est fréquemment utilisé en Java. Par exemple, dans une carte de hachage. Etre immuable, garantit que le hashcode sera toujours le même, de sorte qu'il puisse être mis en cache sans s'inquiéter des modifications. Cela signifie qu'il n'est pas nécessaire de calculer le hashcode à chaque utilisation.
La raison la plus importante selon this article sur DZone:
Chaîne Constante Pool ... Si la chaîne est modifiable, la modification de la chaîne avec une référence entraînera une valeur incorrecte pour les autres références.
Sécurité
La chaîne est largement utilisée en tant que paramètre pour de nombreuses classes Java, par exemple. connexion réseau, ouverture de fichiers, etc. Si String n'était pas immuable, une connexion ou un fichier serait modifié et entraînerait une menace grave pour la sécurité . ...
J'espère que cela vous aidera.
Nous ne pouvons pas être sûrs de ce que pensaient réellement les concepteurs Java lors de la conception de String
, mais nous ne pouvons conclure que ces raisons en fonction des avantages que nous tirons de l'immutabilité des chaînes, dont certaines sont:
Comme indiqué dans Pourquoi String est stocké dans String Constant Pool article, chaque application crée trop d'objets chaîne et afin de préserver la machine virtuelle Java de la création initiale d'un grand nombre d'objets chaîne, puis de les récupérer. La machine virtuelle Java stocke tous les objets chaîne dans une zone mémoire distincte appelée pool de constantes chaînes et réutilise les objets de ce pool mis en cache.
Chaque fois que nous créons un littéral de chaîne, la machine virtuelle Java vérifie d’abord si ce littéral est déjà présent dans le pool constant ou non, et si elle existe, une nouvelle référence commencera à pointer vers le même objet dans SCP.
String a = "Naresh";
String b = "Naresh";
String c = "Naresh";
Dans l'exemple ci-dessus, l'objet de chaîne avec la valeur Naresh
sera créé dans SCP une seule fois et toutes les références a
, b
, c
pointeront sur le même objet, mais que faire si nous essayons d'apporter des modifications dans a
p. Ex. a.replace("a", "")
.
Idéalement, a
devrait avoir la valeur Nresh
mais b
, c
devrait rester inchangé car en tant qu'utilisateur final, nous ne modifions que a
. Et nous savons que a
, b
, c
pointent tous le même objet. Par conséquent, si nous apportons un changement à a
, les autres doivent également refléter ce changement.
Mais l'immutabilité de chaîne nous sauve de ce scénario et, en raison de l'immutabilité de l'objet chaîne, l'objet chaîne Naresh
ne changera jamais. Ainsi, lorsque nous apportons une modification dans a
au lieu d'une modification dans l'objet chaîne Naresh
, la machine virtuelle Java crée un nouvel objet, affectez-la à a
, puis apportez des modifications à cet objet.
Ainsi, le pool de chaînes n'est possible qu'en raison de son immuabilité et si Chaîne n'aurait pas été immuable, la mise en cache et la réutilisation des objets chaîne n'auraient aucune possibilité, car aucune variable n'aurait modifié la valeur et en aurait corrompu d'autres.
Et c’est la raison pour laquelle la machine virtuelle Java la gère très précisément et qu’elle dispose d’une zone mémoire spéciale.
Un objet est appelé thread-safe lorsque plusieurs threads opèrent sur lui mais qu'aucun d'entre eux ne peut corrompre son état et que l'objet conserve le même état pour chaque thread à un moment donné.
Comme nous, un objet immuable ne peut être modifié par personne après sa création, ce qui fait que chaque objet immuable est thread-safe par défaut. Nous n'avons pas besoin de lui appliquer de mesures de sécurité des threads, telles que la création de méthodes synchronisées.
Donc, en raison de sa nature immuable, l'objet string peut être partagé par plusieurs threads et même s'il est manipulé par plusieurs threads, sa valeur ne sera pas modifiée.
Dans chaque application, nous devons transmettre plusieurs secrets, par exemple: nom d'utilisateur de l'utilisateur\mots de passe, URL de connexion et, en général, toutes ces informations sont transmises en tant qu'objet chaîne.
Supposons maintenant que si String n’était pas de nature immuable, cela poserait un risque grave pour la sécurité de l’application, car ces valeurs sont autorisées à être modifiées. Si cela est autorisé, elles pourraient être modifiées en raison d’un code mal écrit ou de toute autre personne qui avoir accès à nos références de variables.
Comme indiqué dans Création d'objets à l'aide de Reflection in Java avec Example , nous pouvons utiliser la méthode Class.forName("class_name")
pour charger une classe en mémoire qui appelle à nouveau d'autres méthodes pour le faire. Et même JVM utilise ces méthodes pour charger des classes.
Mais si vous voyez clairement que toutes ces méthodes acceptent le nom de la classe en tant qu’objet chaîne, les chaînes sont utilisées dans le chargement et l’immuabilité des classes en Java, ce qui permet de garantir que la classe correcte est chargée par ClassLoader
.
Supposons que si String n'aurait pas été immuable et que nous essayons de charger Java.lang.Object
qui devient org.theft.OurObject
entre-temps et maintenant, tous nos objets ont un comportement que quelqu'un peut utiliser pour les objets indésirables.
Si nous allons effectuer des opérations liées au hachage sur un objet, nous devons redéfinir la méthode hashCode()
et essayer de générer un hashcode précis en utilisant l'état de l'objet. Si l'état d'un objet est modifié, cela signifie que son code de hachage doit également changer.
Comme String est immuable, la valeur qu'un objet string est en attente ne sera jamais modifiée, ce qui signifie que son hashcode ne changera pas non plus, ce qui donnera à la classe String l'occasion de mettre en cache son hashcode lors de la création de l'objet.
Oui, l'objet String met en cache son code de hachage au moment de la création, ce qui en fait le candidat idéal pour les opérations liées au hachage, car il n'a pas besoin de recalculer le hachage, ce qui nous fait gagner du temps. C'est pourquoi String est principalement utilisé comme clé HashMap
.
Lire la suite sur Pourquoi String est immuable et définitif en Java .
J'ai lu ce post Pourquoi String est immuable ou final en Java et suppose que suivre peut être la raison la plus importante:
String est immuable en Java car les objets String sont mis en cache dans Pool de chaînes. Depuis la mise en cache, les littéraux sont partagés entre plusieurs clients il y a toujours un risque, où l'action d'un client affecterait tous un autre client.
Tu as raison. String
en Java utilise le concept de String Pool
littéral. Lorsqu'une chaîne est créée et que la chaîne existe déjà dans le pool, la référence de la chaîne existante est renvoyée au lieu de créer un nouvel objet et de renvoyer sa référence. Si une chaîne n'est pas immuable, le fait de modifier la chaîne avec une référence induire une valeur erronée pour les autres références.
J'ajouterais une dernière chose, puisque String
est immuable, il est sécurisé pour les threads multiples et une seule instance de String peut être partagée entre différents threads. Ceci évite l'utilisation de la synchronisation pour la sécurité des threads. Les chaînes sont implicitement thread safe
.
String est immuable parce que: -
1. Conception: - Le pool String n'est possible que parce que String est immuable en Java. Ainsi, Java Runtime économise beaucoup d'espace de segment Java, car différentes variables String peuvent faire référence à la même variable String dans le pool. Si String n'avait pas été immuable, son internat n'aurait pas été possible, car si une variable quelconque avait modifié la valeur, elle aurait également été répercutée sur d'autres variables.
2. Sécurité: - Si String n'est pas immuable, l'application posera de graves problèmes de sécurité. Par exemple, le nom d'utilisateur et le mot de passe de la base de données sont transmis sous forme de chaîne pour obtenir une connexion à la base de données et dans la programmation du socket. Les détails de l'hôte et du port sont transmis sous forme de chaîne. Puisque String est immuable, sa valeur ne peut pas être modifiée, sinon tout pirate informatique pourrait changer la valeur référencée pour causer des problèmes de sécurité dans l’application.
3. Thread Safe: - Puisque String est immuable, il est sans danger pour le multithreading et une seule instance de String peut être partagée entre différents threads. Cela évite l'utilisation de la synchronisation pour la sécurité des threads, les chaînes sont implicitement thread-safe
4. classloader: - Les chaînes sont utilisées dans le chargeur de classes Java et l'immutabilité garantit à la classe que celui-ci est chargé par Classloader. Par exemple, imaginez une instance dans laquelle vous essayez de charger la classe Java.sql.Connection mais où la valeur référencée est remplacée par la classe myhacked.Connection qui peut modifier votre base de données.
5. Mise en cache: - Puisque String est immuable, son hashcode est mis en cache au moment de la création et il n’a pas besoin de le calculer à nouveau. Cela en fait un excellent candidat pour la clé dans une carte et son traitement est rapide par rapport aux autres objets de clé HashMap. C'est pourquoi String est principalement utilisé Object en tant que clés HashMap . Ci-dessus figurent certaines des raisons pour lesquelles je pense que cela montre les avantages de l'immuabilité de String. C'est une fonctionnalité intéressante de la classe Java String et la rend spéciale.
En plus des bonnes réponses, je voulais ajouter quelques points. Tout comme Strings, Array contient une référence au début du tableau. Par conséquent, si vous créez deux tableaux arr1
et arr2
et que vous exécutez quelque chose comme arr2 = arr1
, la référence arr2
sera identique à arr1
. Par conséquent, la modification de la valeur de l'un d'entre eux entraînera une modification de la valeur. un autre par exemple
public class Main {
public static void main(String[] args) {
int[] a = {1, 2, 3, 4};
int[] b = a;
a[0] = 8;
b[1] = 7;
System.out.println("A: " + a[0] + ", B: " + b[0]);
System.out.println("A: " + a[1] + ", B: " + b[1]);
//outputs
//A: 8, B: 8
//A: 7, B: 7
}
}
Non seulement cela causerait des bugs dans le code, il pourrait également (et sera) exploité par un utilisateur malveillant. Supposons que si vous avez un système qui modifie le mot de passe administrateur. L'utilisateur doit d'abord entrer la newPassword
et ensuite la oldPassword
si la oldPassword
est identique à la adminPass
le programme change le mot de passe de adminPass = newPassword
. Supposons que le nouveau mot de passe ait la même référence que le mot de passe admin. Ainsi, un mauvais programmeur peut créer une variable temp
qui contiendra le mot de passe admin avant que les utilisateurs ne saisissent des données si la variable oldPassword
est égale à temp
. Sinon, le mot de passe est modifié. adminPass = temp
. Quelqu'un sachant que pourrait entrer facilement le nouveau mot de passe et ne jamais entrer l'ancien mot de passe et abracadabra il a un accès administrateur. Une autre chose que je ne comprenais pas quand j'ai appris à propos de Strings, c'est pourquoi JVM ne crée pas une nouvelle chaîne pour chaque objet, mais une place unique en mémoire pour cela. Vous pouvez simplement le faire en utilisant new String("str");
La raison pour laquelle vous ne voudriez pas toujours utiliser new
est dû au fait que la mémoire n'est pas efficace et qu'elle est plus lente dans la plupart des cas en savoir plus .
La chaîne est considérée comme immuable par les systèmes micro Sun, car elle peut être utilisée comme clé dans la collection de cartes
La principale raison pour laquelle une chaîne est rendue immuable en Java est la considération Sécurité. Suivant serait Caching.
Je crois que d’autres raisons données ici, telles que l’efficacité, la concurrence, la conception et le pool de string découlent du fait que String est rendu immuable. Pour par exemple. Un pool de chaînes pourrait être créé car String était immuable et non l'inverse.
Vérifiez la transcription de l'interview de Gosling ici
D'un point de vue stratégique, ils ont tendance à être plus souvent sans problème. Et il y a généralement des choses que vous pouvez faire avec des immuables, que vous ne pouvez pas faire avec des choses mutables, telles que mettre en cache le résultat. Si vous transmettez une chaîne à une méthode d'ouverture de fichier ou si vous transmettez une chaîne à un constructeur pour une étiquette dans une interface utilisateur, dans certaines API (comme dans de nombreuses API Windows), vous transmettez un tableau de caractères. Le destinataire de cet objet doit vraiment le copier, car il ne sait rien de sa durée de conservation. Et ils ne savent pas ce qui arrive à l'objet, s'il est changé sous leurs pieds.
Vous finissez par être presque obligé de répliquer l'objet car vous ne savez pas si vous en êtes le propriétaire ou non. Et l’un des aspects positifs des objets immuables est que la réponse est: "Oui, bien sûr." Parce que la question de la propriété, qui a le droit de la changer, n'existe pas.
Une des choses qui a forcé Strings à être immuable était la sécurité. Vous avez une méthode d'ouverture de fichier. Vous passez une chaîne à elle. Et puis, il effectue toutes sortes de vérifications d’authentification avant de passer à l’appel du système d’exploitation. Si vous parvenez à faire quelque chose qui a effectivement muté la chaîne, après le contrôle de sécurité et avant l'appel du système d'exploitation, boum, c'est parti. Mais les chaînes sont immuables, ce genre d'attaque ne fonctionne pas. Cet exemple précis est ce qui a vraiment exigé que Les chaînes sont immuables
Si HELLO
est votre chaîne, vous ne pouvez pas changer HELLO
en HILLO
. Cette propriété est appelée propriété d'immutabilité.
Vous pouvez avoir plusieurs variables de chaîne de pointeur pour pointer HELLO String.
Mais si HELLO est char Array, vous pouvez remplacer HELLO par HILLO. Par exemple,
char[] charArr = 'HELLO';
char[1] = 'I'; //you can do this
Réponse:
Les langages de programmation ont des variables de données immuables, ce qui permet de les utiliser comme clés dans une paire clé/valeur. Les variables de chaîne sont utilisées comme clés/indices, elles sont donc immuables .
La classe String est FINAL
, cela signifie que vous ne pouvez créer aucune classe qui en hérite, modifier la structure de base et rendre le Sting mutable.
Une autre variable d'instance et les méthodes de la classe String fournies sont telles que vous ne pouvez pas modifier l'objet String
une fois créé.
La raison pour laquelle vous avez ajouté ne rend pas la chaîne immuable du tout. Tout cela indique comment la chaîne est stockée dans le tas.