web-dev-qa-db-fra.com

Le retour de String.intern () expliqué

Considérer:

String s1 = new StringBuilder("Cattie").append(" & Doggie").toString();
System.out.println(s1.intern() == s1); // true why?
System.out.println(s1 == "Cattie & Doggie"); // true another why?

String s2 = new StringBuilder("ja").append("va").toString();
System.out.println(s2.intern() == s2); // false

String s3 = new String("Cattie & Doggie");
System.out.println(s3.intern() == s3); // false
System.out.println(s3 == "Cattie & Doggie"); // false

Je ne comprends pas pourquoi ils résultent différemment par la valeur renvoyée de String.intern() qui dit:

Lorsque la méthode intern est invoquée, si le pool contient déjà une chaîne égale à cet objet String tel que déterminé par la méthode equals (Object), la chaîne du pool est renvoyée. Sinon, cet objet String est ajouté au pool et une référence à cet objet String est renvoyée.

Surtout après ces deux tests:

assertFalse("new String() should create a new instance", new String("jav") == "jav");
assertFalse("new StringBuilder() should create a new instance",
    new StringBuilder("jav").toString() == "jav");

J'ai lu une fois un article parlant de certains special strings Internés avant tout le reste, mais c'est un vrai flou maintenant.

S'il y a des chaînes pre-interned, Existe-t-il un moyen d'en obtenir une sorte de liste? Je suis simplement curieux de savoir ce qu'ils peuvent être.


Actualisé

Grâce à l'aide de @Eran et @Slaw, je peux enfin expliquer ce qui vient de se passer là-bas pour la sortie

true
true
false
false
false
  1. Puisque "Cattie & Doggie" N'existe pas dans le pool, s1.intern () placera la référence d'objet actuelle dans le pool et se renverra, donc s1.intern() == s1;
  2. "Cattie & Doggie" Déjà dans le pool maintenant, donc le littéral de chaîne "Cattie & Doggie" Utilisera simplement la référence dans le pool qui est en fait s1, Donc encore une fois nous avons true;
  3. new StringBuilder().toString() créera une nouvelle instance alors que "Java" est déjà dans le pool, puis la référence dans pool sera retournée lors de l'appel de s2.intern(), donc s2.intern() != s2 et nous avons false;
  4. new String() renverra également une nouvelle instance, mais lorsque nous essaierons de s3.intern(), elle renverra la référence précédemment stockée dans le pool qui est en fait s1 donc s3.intern() != s3 et nous avons false;
  5. Comme # 2 déjà discuté, le littéral de chaîne "Cattie & Doggie" Renverra la référence déjà stockée dans le pool (qui est en fait s1), Donc s3 != "Cattie & Doggie" Et nous avons false encore.

Merci à @Sunny de fournir une astuce pour obtenir toutes les chaînes interned.

20
Hearen

Les littéraux de chaîne (ceux qui sont codés en dur comme "une chaîne") sont déjà internés pour vous par le compilateur. Mais les chaînes acquises par programme ne le sont pas et ne seront internées que si vous utilisez la méthode .intern().

Habituellement, vous n'internez pas les chaînes manuellement, sauf si vous savez que vous stockerez en mémoire un grand nombre de chaînes répétitives, de sorte que vous pouvez économiser beaucoup de mémoire de cette façon.

Cela est expliqué ici: Qu'est-ce que Java String interning?

0
maslan