Je suis confus au sujet de StringPool en Java. Je suis tombé dessus en lisant le chapitre sur les chaînes en Java. Veuillez m'aider à comprendre, en termes simples, ce que StringPool fait réellement.
Réponses
Trop de publicités?Cette impression true
(même si nous n'utilisons pas equals
méthode : manière correcte de comparer des chaînes de caractères)
String s = "a" + "bc";
String t = "ab" + "c";
System.out.println(s == t);
Lorsque le compilateur optimise vos chaînes de caractères, il voit que les deux s
y t
ont la même valeur et vous n'avez donc besoin que d'un seul objet chaîne. C'est sûr car String
est immuable en Java.
En conséquence, les deux s
y t
pointent vers le même objet et un peu de mémoire économisée.
Le nom "string pool" vient de l'idée que toutes les chaînes de caractères déjà définies sont stockées dans un "pool" et qu'avant de créer de nouvelles chaînes de caractères, il faut en créer de nouvelles. String
le compilateur d'objets vérifie si une telle chaîne est déjà définie.
Je ne pense pas qu'il fasse grand chose, on dirait que c'est juste un cache pour les chaînes littérales. Si vous avez plusieurs chaînes dont les valeurs sont les mêmes, elles pointeront toutes vers le même littéral de chaîne dans le pool de chaînes.
String s1 = "Arul"; //case 1
String s2 = "Arul"; //case 2
Dans le cas 1, le littéral s1 est nouvellement créé et conservé dans le pool. Mais dans le cas 2, le s2 littéral fait référence au s1, il n'en créera pas un nouveau à la place.
if(s1 == s2) System.out.println("equal"); //Prints equal.
String n1 = new String("Arul");
String n2 = new String("Arul");
if(n1 == n2) System.out.println("equal"); //No output.
Commençons par une citation de la spécification de la machine virtuelle :
Le chargement d'une classe ou d'une interface qui contient un littéral String peut créer un nouvel objet String (§2.4.8) pour représenter ce littéral. Cela ne peut pas se produire si un objet String a déjà été créé pour représenter une occurrence précédente de ce littéral, ou si la méthode String.intern a été invoquée sur un objet String représentant la même chaîne que le littéral.
Cela peut ne pas se produire - C'est un indice, qu'il y a quelque chose de spécial à propos String
objets. En général, l'invocation d'un constructeur toujours créer une nouvelle instance de la classe. Ce n'est pas le cas avec les chaînes de caractères, en particulier lorsque les objets Chaîne sont "créés" avec des littéraux. Ces chaînes sont stockées dans un magasin global (pool) - ou du moins les références sont conservées dans un pool, et chaque fois qu'une nouvelle instance d'une chaîne déjà connue est nécessaire, la machine virtuelle renvoie une référence à l'objet du pool. En pseudo-code, cela peut se passer comme suit :
1: a := "one"
--> if(pool[hash("one")] == null) // true
pool[hash("one") --> "one"]
return pool[hash("one")]
2: b := "one"
--> if(pool[hash("one")] == null) // false, "one" already in pool
pool[hash("one") --> "one"]
return pool[hash("one")]
Donc dans ce cas, les variables a
y b
contiennent des références à le même objet. Dans ce cas, nous avons (a == b) && (a.equals(b)) == true
.
Ce n'est pas le cas si on utilise le constructeur :
1: a := "one"
2: b := new String("one")
Encore une fois, "one"
est créée sur le pool mais ensuite nous créons une nouvelle instance à partir du même littéral, et dans ce cas, cela conduit à (a == b) && (a.equals(b)) == false
Alors pourquoi avons-nous une piscine à cordes ? Les chaînes et surtout les littéraux de chaînes sont largement utilisés dans le code Java typique. Et elles sont immuables. Et le fait d'être immuable permet de mettre les chaînes en cache pour économiser de la mémoire et augmenter les performances (moins d'effort pour la création, moins de déchets à collecter).
En tant que programmeurs, nous n'avons pas besoin de nous préoccuper du pool de chaînes de caractères, tant que nous gardons à l'esprit :
-
(a == b) && (a.equals(b))
peut êtretrue
ofalse
( toujours utiliserequals
pour comparer des chaînes de caractères) - N'utilisez pas la réflexion pour changer le support.
char[]
d'une chaîne (car vous ne savez pas qui est en train d'utiliser cette chaîne)
Lorsque la JVM charge des classes, ou voit une chaîne de caractères littérale, ou du code intern
s une chaîne de caractères, il ajoute la chaîne à un pool majoritairement caché qui contient une copie de chaque chaîne de ce type. Si une autre copie est ajoutée, le runtime l'organise de manière à ce que tous les littéraux fassent référence au même objet chaîne. Ceci est appelé "interning". Si vous dites quelque chose comme
String s = "test";
return (s == "test");
il reviendra true
car le premier et le second "test" sont en fait le même objet. Comparer des chaînes de caractères internées de cette façon peut être très difficile, beaucoup plus vite que String.equals
car il n'y a qu'une seule comparaison de référence au lieu d'une série de comparaisons. char
comparaisons.
Vous pouvez ajouter une chaîne au pool en appelant String.intern()
qui vous renverra la version poolée de la chaîne (qui pourrait être la même chaîne que celle que vous êtes en train d'interner, mais vous seriez fou de vous fier à cela -- vous ne pouvez souvent pas être sûr du code qui a été chargé et exécuté jusqu'à présent et qui a interné la même chaîne). La version mutualisée (la chaîne retournée par intern
) sera égal à tout littéral identique. Par exemple :
String s1 = "test";
String s2 = new String("test"); // "new String" guarantees a different object
System.out.println(s1 == s2); // should print "false"
s2 = s2.intern();
System.out.println(s1 == s2); // should print "true"
http://www.xyzws.com/Javafaq/what-is-string-literal-pool/3 . Une autre réponse que vous pouvez vérifier.