C'est un bel article qui décrit deux raisons déjà mentionnées sur les réponses ci-dessus:
- Sécurité : le système peut distribuer des bits sensibles d'informations en lecture seule sans se soucier de leur altération
- Performances : les données immuables sont très utiles pour rendre les choses thread-safe.
Et c'est probablement le commentaire le plus détaillé de cet article. Cela a à voir avec le pool de chaînes en Java et les problèmes de sécurité. Il s'agit de savoir comment décider de ce qui entre dans le pool de cordes. En supposant que les deux chaînes sont égales si leur séquence de caractères est la même, alors nous avons une condition de concurrence sur qui y arrive en premier et avec des problèmes de sécurité. Sinon, le pool de chaînes contiendra des chaînes redondantes, perdant ainsi l'avantage de l'avoir en premier lieu. Lisez-le par vous-même, d'accord?
L'extension de String ferait des ravages avec les égaux et les stagiaires. JavaDoc dit égal:
Compare cette chaîne à l'objet spécifié. Le résultat est vrai si et seulement si l'argument n'est pas nul et est un objet String qui représente la même séquence de caractères que cet objet.
En supposant que ce java.lang.String
n'était pas définitif, a SafeString
pourrait égaler a String
, et vice versa; parce qu'ils représenteraient la même séquence de caractères.
Que se passerait-il si vous postuliez intern
à un SafeString
- irait SafeString
-il dans le pool de chaînes de la JVM? Les ClassLoader
objets et tous les objets auxquels les SafeString
références sont conservées seraient alors verrouillés pendant toute la durée de vie de la machine virtuelle Java. Vous obtiendrez une condition de concurrence sur qui pourrait être le premier à interner une séquence de personnages - peut-être que vous SafeString
gagneriez, peut-être un String
, ou peut-être un SafeString
chargé par un chargeur de classe différent (donc une classe différente).
Si vous gagniez la course dans la piscine, ce serait un vrai singleton et les gens pourraient accéder à l'ensemble de votre environnement (bac à sable) par réflexion et secretKey.intern().getClass().getClassLoader()
.
Ou la JVM pourrait bloquer ce trou en s'assurant que seuls des objets String concrets (et aucune sous-classe) étaient ajoutés au pool.
Si égal a été implémenté de telle sorte que SafeString
! = String
Alors SafeString.intern
! = String.intern
, Et SafeString
devrait être ajouté au pool. La piscine deviendrait alors une piscine <Class, String>
au lieu de<String>
et tout ce dont vous auriez besoin pour entrer dans le pool serait un nouveau chargeur de classe.