Pourquoi String est immuable en Java?

Pourquoi String est immuable en Java?

1. introduction

En Java, les chaînes sont immuables. Une question évidente qui prévaut dans les entretiens est la suivante: "Pourquoi les chaînes sont-elles conçues comme immuables en Java?"

James Gosling, le créateur de Java,was once asked in an interview quand doit-on utiliser des immuables, ce à quoi il répond:

Je voudrais utiliser un immuable chaque fois que je peux.

Il soutient en outre son argument en énonçant des fonctionnalités que l'immuabilité fournit, telles que la mise en cache, la sécurité, la réutilisation facile sans réplication, etc.

Dans ce didacticiel, nous explorerons plus en détail pourquoi les concepteurs de langage Java ont décidé de garderString immuable.

2. Qu'est-ce qu'un objet immuable?

Un objet immuable est unobject whose internal state remains constant after it has been entirely created. Cela signifie qu'une fois que l'objet a été affecté à une variable, nous ne pouvons ni mettre à jour la référence, ni transformer l'état interne par quelque moyen que ce soit.

Nous avons un article séparé qui traite en détail des objets immuables. Pour plus d'informations, lisez l'article deImmutable Objects in Java.

3. PourquoiString est-il immuable en Java?

Les avantages clés de garder cette classe immuable sont la mise en cache, la sécurité, la synchronisation et les performances.

Voyons comment ces choses fonctionnent.

3.1. Présentation du poolString

LeString est la structure de données la plus utilisée. La mise en cache des littérauxString et leur réutilisation économise beaucoup d'espace sur le tas car différentes variablesString font référence au même objet dans le poolString. Le pool de stagiaires deString sert exactement ce but.

Le pool de chaînes Java estthe special memory region where Strings are stored by the JVM. LesStrings étant immuables en Java, la JVM optimise la quantité de mémoire qui leur est allouée en ne stockant qu'une seule copie de chaque littéralString dans le pool. Ce processus s'appelle interning:

String s1 = "Hello World";
String s2 = "Hello World";

assertThat(s1 == s2).isTrue();

En raison de la présence du poolString dans l'exemple précédent, deux variables différentes pointent vers le même objetString depuis le pool, économisant ainsi une ressource mémoire cruciale.

image

Nous avons un article séparé consacré au pool JavaString. Pour plus d'informations,head on over to that article.

3.2. Sécurité

LeString est largement utilisé dans les applications Java pour stocker des informations sensibles telles que les noms d'utilisateur, les mots de passe, les URL de connexion, les connexions réseau, etc. Il est également largement utilisé par les chargeurs de classes JVM lors du chargement de classes.

Par conséquent, la sécurisation de la classeString est cruciale pour la sécurité de l'ensemble de l'application en général. Par exemple, considérons cet extrait de code simple:

void criticalMethod(String userName) {
    // perform security checks
    if (!isAlphaNumeric(userName)) {
        throw new SecurityException();
    }

    // do some secondary tasks
    initializeDatabase();

    // critical task
    connection.executeUpdate("UPDATE Customers SET Status = 'Active' " +
      " WHERE UserName = '" + userName + "'");
}

Dans l'extrait de code ci-dessus, disons que nous avons reçu un objetString d'une source non fiable. Nous effectuons toutes les vérifications de sécurité nécessaires au départ pour vérifier si leString est uniquement alphanumérique, suivi de quelques opérations supplémentaires.

Rappelez-vous que notre méthode d'appel source non fiable a toujours une référence à cet objetuserName.

If Strings were mutable, then by the time we execute the update, we can’t be sure that the String we received, even after performing security checks, would be safe. La méthode de l'appelant non fiable a toujours la référence et peut modifier lesString entre les contrôles d'intégrité. En rendant ainsi notre requête sujette à des injections SQL dans ce cas. Ainsi, lesStringsmutables peuvent entraîner une dégradation de la sécurité au fil du temps.

Il peut également arriver que leStringuserName soit visible par un autre thread, qui pourrait alors changer sa valeur après le contrôle d'intégrité.

En général, l'immuabilité vient à notre secours dans ce cas, car il est plus facile d'utiliser du code sensible lorsque les valeurs ne changent pas, car il y a moins d'entrelacements d'opérations susceptibles d'affecter le résultat.

3.3. Synchronisation

Le fait d'être immuable rend automatiquement le thread deString sûr car il ne sera pas modifié lors de l'accès à partir de plusieurs threads.

D'oùimmutable objects, in general, can be shared across multiple threads running simultaneously. They’re also thread-safe car si un thread change la valeur, alors au lieu de la modifier, un nouveauString serait créé dans le pool deString. Par conséquent,Strings sont sans danger pour le multi-threading.

3.4. Mise en cache du hashcode

Étant donné que les objetsString sont abondamment utilisés comme structure de données, ils sont également largement utilisés dans les implémentations de hachage telles queHashMap,HashTable,HashSet, etc. Lors de l'utilisation de ces implémentations de hachage, la méthodehashCode() est appelée assez fréquemment pour le compartimentage.

L'immuabilité garantit àStrings que leur valeur ne changera pas. Doncthe hashCode() method is overridden in String class to facilitate caching, such that the hash is calculated and cached during the first hashCode() call and the same value is returned ever since.

Ceci, à son tour, améliore les performances des collections qui utilisent des implémentations de hachage lorsqu'elles sont utilisées avec des objetsString.

D'un autre côté, mutableStrings produirait deux hashcodes différents au moment de l'insertion et de la récupération si le contenu deString était modifié après l'opération, perdant potentiellement l'objet de valeur dans lesMap.

3.5. Performance

Comme nous l'avons vu précédemment, le pool deString existe car lesStrings sont immuables. À son tour, il améliore les performances en économisant la mémoire du tas et un accès plus rapide aux implémentations de hachage lorsqu'il est utilisé avecStrings.

Étant donné queString est la structure de données la plus largement utilisée, l'amélioration des performances deString a un effet considérable sur l'amélioration des performances de l'ensemble de l'application en général.

4. Conclusion

Grâce à cet article, nous pouvons conclure queStrings are immutable precisely so that their references can be treated as a normal variable and one can pass them around, between methods and across threads, without worrying about whether the actual String object it’s pointing to will change.

Nous avons également appris quelles pourraient être les autres raisons qui ont incité les concepteurs de langage deJava à rendre cette classe immuable.